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 17 package com.google.turbine.binder; 18 19 import static com.google.common.base.Preconditions.checkNotNull; 20 import static java.util.Objects.requireNonNull; 21 22 import com.google.common.base.Joiner; 23 import com.google.common.collect.ImmutableList; 24 import com.google.common.collect.ImmutableMap; 25 import com.google.common.collect.Iterables; 26 import com.google.turbine.binder.bound.EnumConstantValue; 27 import com.google.turbine.binder.bound.TurbineAnnotationValue; 28 import com.google.turbine.binder.bound.TurbineClassValue; 29 import com.google.turbine.binder.bound.TypeBoundClass; 30 import com.google.turbine.binder.bound.TypeBoundClass.FieldInfo; 31 import com.google.turbine.binder.bound.TypeBoundClass.MethodInfo; 32 import com.google.turbine.binder.env.CompoundEnv; 33 import com.google.turbine.binder.env.Env; 34 import com.google.turbine.binder.lookup.LookupKey; 35 import com.google.turbine.binder.lookup.LookupResult; 36 import com.google.turbine.binder.lookup.MemberImportIndex; 37 import com.google.turbine.binder.lookup.Scope; 38 import com.google.turbine.binder.sym.ClassSymbol; 39 import com.google.turbine.binder.sym.FieldSymbol; 40 import com.google.turbine.binder.sym.Symbol; 41 import com.google.turbine.diag.SourceFile; 42 import com.google.turbine.diag.TurbineDiagnostic; 43 import com.google.turbine.diag.TurbineError; 44 import com.google.turbine.diag.TurbineError.ErrorKind; 45 import com.google.turbine.diag.TurbineLog.TurbineLogWithSource; 46 import com.google.turbine.model.Const; 47 import com.google.turbine.model.Const.ArrayInitValue; 48 import com.google.turbine.model.Const.CharValue; 49 import com.google.turbine.model.Const.ConstCastError; 50 import com.google.turbine.model.Const.DoubleValue; 51 import com.google.turbine.model.Const.FloatValue; 52 import com.google.turbine.model.Const.StringValue; 53 import com.google.turbine.model.Const.Value; 54 import com.google.turbine.model.TurbineConstantTypeKind; 55 import com.google.turbine.model.TurbineFlag; 56 import com.google.turbine.model.TurbineTyKind; 57 import com.google.turbine.tree.Tree; 58 import com.google.turbine.tree.Tree.ArrayInit; 59 import com.google.turbine.tree.Tree.Binary; 60 import com.google.turbine.tree.Tree.ClassLiteral; 61 import com.google.turbine.tree.Tree.ClassTy; 62 import com.google.turbine.tree.Tree.Conditional; 63 import com.google.turbine.tree.Tree.ConstVarName; 64 import com.google.turbine.tree.Tree.Expression; 65 import com.google.turbine.tree.Tree.Ident; 66 import com.google.turbine.tree.Tree.Paren; 67 import com.google.turbine.tree.Tree.PrimTy; 68 import com.google.turbine.tree.Tree.TypeCast; 69 import com.google.turbine.tree.Tree.Unary; 70 import com.google.turbine.tree.TurbineOperatorKind; 71 import com.google.turbine.type.AnnoInfo; 72 import com.google.turbine.type.Type; 73 import java.util.ArrayDeque; 74 import java.util.Iterator; 75 import java.util.LinkedHashMap; 76 import java.util.Map; 77 import org.jspecify.annotations.Nullable; 78 79 /** 80 * Constant expression evaluation. 81 * 82 * <p>This class requires strict floating point operations. In Java SE 17 and later, the Java SE 83 * Platform always requires strict evaluation of floating-point expressions. 84 */ 85 public class ConstEvaluator { 86 87 /** The symbol of the originating class, for visibility checks. */ 88 private final @Nullable ClassSymbol origin; 89 90 /** The symbol of the enclosing class, for lexical field lookups. */ 91 private final @Nullable ClassSymbol owner; 92 93 /** Member imports of the enclosing compilation unit. */ 94 private final MemberImportIndex memberImports; 95 96 /** The current source file. */ 97 private final SourceFile source; 98 99 /** The constant variable environment. */ 100 private final Env<FieldSymbol, Value> values; 101 102 /** The class environment. */ 103 private final CompoundEnv<ClassSymbol, TypeBoundClass> env; 104 105 private final Scope scope; 106 107 private final TurbineLogWithSource log; 108 ConstEvaluator( @ullable ClassSymbol origin, @Nullable ClassSymbol owner, MemberImportIndex memberImports, SourceFile source, Scope scope, Env<FieldSymbol, Value> values, CompoundEnv<ClassSymbol, TypeBoundClass> env, TurbineLogWithSource log)109 public ConstEvaluator( 110 @Nullable ClassSymbol origin, 111 @Nullable ClassSymbol owner, 112 MemberImportIndex memberImports, 113 SourceFile source, 114 Scope scope, 115 Env<FieldSymbol, Value> values, 116 CompoundEnv<ClassSymbol, TypeBoundClass> env, 117 TurbineLogWithSource log) { 118 119 this.origin = origin; 120 this.owner = owner; 121 this.memberImports = memberImports; 122 this.source = source; 123 this.values = values; 124 this.env = env; 125 this.scope = scope; 126 this.log = log; 127 } 128 129 /** Evaluates the given expression's value. */ eval(Tree t)130 public @Nullable Const eval(Tree t) { 131 switch (t.kind()) { 132 case LITERAL: 133 { 134 Value a = (Value) ((Tree.Literal) t).value(); 135 if (a == null) { 136 return null; 137 } 138 switch (a.constantTypeKind()) { 139 case CHAR: 140 case INT: 141 case LONG: 142 case FLOAT: 143 case DOUBLE: 144 case BOOLEAN: 145 case STRING: 146 return a; 147 case SHORT: 148 case BYTE: 149 case NULL: 150 } 151 throw new AssertionError(a.constantTypeKind()); 152 } 153 case VOID_TY: 154 throw new AssertionError(t.kind()); 155 case CONST_VAR_NAME: 156 return evalConstVar((ConstVarName) t); 157 case CLASS_LITERAL: 158 return evalClassLiteral((ClassLiteral) t); 159 case BINARY: 160 return evalBinary((Binary) t); 161 case PAREN: 162 return eval(((Paren) t).expr()); 163 case TYPE_CAST: 164 return evalCast((TypeCast) t); 165 case UNARY: 166 return evalUnary((Unary) t); 167 case CONDITIONAL: 168 return evalConditional((Conditional) t); 169 case ARRAY_INIT: 170 return evalArrayInit((ArrayInit) t); 171 case ANNO_EXPR: 172 return evalAnno(((Tree.AnnoExpr) t).value()); 173 default: 174 throw error(t.position(), ErrorKind.EXPRESSION_ERROR); 175 } 176 } 177 178 /** Evaluates a class literal. */ evalClassLiteral(ClassLiteral t)179 Const evalClassLiteral(ClassLiteral t) { 180 return new TurbineClassValue(evalClassLiteralType(t.type())); 181 } 182 evalClassLiteralType(Tree.Type type)183 private Type evalClassLiteralType(Tree.Type type) { 184 switch (type.kind()) { 185 case PRIM_TY: 186 return Type.PrimTy.create(((PrimTy) type).tykind(), ImmutableList.of()); 187 case VOID_TY: 188 return Type.VOID; 189 case CLASS_TY: 190 return resolveClass((ClassTy) type); 191 case ARR_TY: 192 return Type.ArrayTy.create( 193 evalClassLiteralType(((Tree.ArrTy) type).elem()), ImmutableList.of()); 194 default: 195 throw new AssertionError(type.kind()); 196 } 197 } 198 199 /** 200 * Resolves the {@link ClassSymbol} for the given {@link Tree.ClassTy}, with handling for 201 * non-canonical qualified type names. 202 * 203 * <p>Similar to {@code HierarchyBinder#resolveClass}, except we can't unconditionally consider 204 * members of the current class (e.g. when binding constants inside annotations on that class), 205 * and when we do want to consider members we can rely on them being in the current scope (it 206 * isn't completed during the hierarchy phase). 207 */ resolveClass(ClassTy classTy)208 private Type resolveClass(ClassTy classTy) { 209 ArrayDeque<Ident> flat = new ArrayDeque<>(); 210 for (ClassTy curr = classTy; curr != null; curr = curr.base().orElse(null)) { 211 flat.addFirst(curr.name()); 212 } 213 LookupResult result = scope.lookup(new LookupKey(ImmutableList.copyOf(flat))); 214 if (result == null) { 215 log.error(classTy.position(), ErrorKind.CANNOT_RESOLVE, flat.getFirst()); 216 return Type.ErrorTy.create(flat, ImmutableList.of()); 217 } 218 if (result.sym().symKind() != Symbol.Kind.CLASS) { 219 throw error(classTy.position(), ErrorKind.UNEXPECTED_TYPE_PARAMETER, flat.getFirst()); 220 } 221 ClassSymbol classSym = (ClassSymbol) result.sym(); 222 for (Ident bit : result.remaining()) { 223 classSym = resolveNext(classTy.position(), classSym, bit); 224 } 225 return Type.ClassTy.asNonParametricClassTy(classSym); 226 } 227 resolveNext(int position, ClassSymbol sym, Ident bit)228 private ClassSymbol resolveNext(int position, ClassSymbol sym, Ident bit) { 229 ClassSymbol next = Resolve.resolve(env, origin, sym, bit); 230 if (next == null) { 231 throw error( 232 position, ErrorKind.SYMBOL_NOT_FOUND, new ClassSymbol(sym.binaryName() + '$' + bit)); 233 } 234 return next; 235 } 236 237 /** Evaluates a reference to another constant variable. */ evalConstVar(ConstVarName t)238 @Nullable Const evalConstVar(ConstVarName t) { 239 FieldInfo field = resolveField(t); 240 if (field == null) { 241 return null; 242 } 243 if ((field.access() & TurbineFlag.ACC_ENUM) == TurbineFlag.ACC_ENUM) { 244 return new EnumConstantValue(field.sym()); 245 } 246 if (field.value() != null) { 247 return field.value(); 248 } 249 return values.get(field.sym()); 250 } 251 resolveField(ConstVarName t)252 FieldInfo resolveField(ConstVarName t) { 253 Ident simpleName = t.name().get(0); 254 FieldInfo field = lexicalField(env, owner, simpleName); 255 if (field != null) { 256 return field; 257 } 258 field = resolveQualifiedField(t); 259 if (field != null) { 260 return field; 261 } 262 ClassSymbol classSymbol = memberImports.singleMemberImport(simpleName.value()); 263 if (classSymbol != null) { 264 field = Resolve.resolveField(env, origin, classSymbol, simpleName); 265 if (field != null) { 266 return field; 267 } 268 } 269 Iterator<ClassSymbol> it = memberImports.onDemandImports(); 270 while (it.hasNext()) { 271 field = Resolve.resolveField(env, origin, it.next(), simpleName); 272 if (field == null) { 273 continue; 274 } 275 // resolve handles visibility of inherited members; on-demand imports of private members are 276 // a special case 277 if ((field.access() & TurbineFlag.ACC_PRIVATE) == TurbineFlag.ACC_PRIVATE) { 278 continue; 279 } 280 return field; 281 } 282 throw error( 283 t.position(), 284 ErrorKind.CANNOT_RESOLVE, 285 String.format("field %s", Iterables.getLast(t.name()))); 286 } 287 resolveQualifiedField(ConstVarName t)288 private @Nullable FieldInfo resolveQualifiedField(ConstVarName t) { 289 if (t.name().size() <= 1) { 290 return null; 291 } 292 LookupResult result = scope.lookup(new LookupKey(t.name())); 293 if (result == null) { 294 return null; 295 } 296 if (result.remaining().isEmpty()) { 297 // unexpectedly resolved qualified name to a type 298 return null; 299 } 300 ClassSymbol sym = (ClassSymbol) result.sym(); 301 for (int i = 0; i < result.remaining().size() - 1; i++) { 302 sym = Resolve.resolve(env, sym, sym, result.remaining().get(i)); 303 if (sym == null) { 304 return null; 305 } 306 } 307 return Resolve.resolveField(env, origin, sym, Iterables.getLast(result.remaining())); 308 } 309 310 /** Search for constant variables in lexically enclosing scopes. */ lexicalField( Env<ClassSymbol, TypeBoundClass> env, @Nullable ClassSymbol sym, Ident name)311 private @Nullable FieldInfo lexicalField( 312 Env<ClassSymbol, TypeBoundClass> env, @Nullable ClassSymbol sym, Ident name) { 313 while (sym != null) { 314 TypeBoundClass info = env.getNonNull(sym); 315 FieldInfo field = Resolve.resolveField(env, origin, sym, name); 316 if (field != null) { 317 return field; 318 } 319 sym = info.owner(); 320 } 321 return null; 322 } 323 324 /** Casts the value to the given type. */ cast(int position, Type ty, Const value)325 private Const cast(int position, Type ty, Const value) { 326 checkNotNull(value); 327 switch (ty.tyKind()) { 328 case CLASS_TY: 329 case TY_VAR: 330 return value; 331 case PRIM_TY: 332 if (!value.kind().equals(Const.Kind.PRIMITIVE)) { 333 throw error(position, ErrorKind.EXPRESSION_ERROR); 334 } 335 return coerce(position, (Value) value, ((Type.PrimTy) ty).primkind()); 336 default: 337 throw new AssertionError(ty.tyKind()); 338 } 339 } 340 341 /** Casts the constant value to the given type. */ coerce(int position, Value value, TurbineConstantTypeKind kind)342 Value coerce(int position, Value value, TurbineConstantTypeKind kind) { 343 switch (kind) { 344 case BYTE: 345 return asByte(position, value); 346 case SHORT: 347 return asShort(position, value); 348 case INT: 349 return asInt(position, value); 350 case LONG: 351 return asLong(position, value); 352 case FLOAT: 353 return asFloat(position, value); 354 case DOUBLE: 355 return asDouble(position, value); 356 case CHAR: 357 return asChar(position, value); 358 case BOOLEAN: 359 case STRING: 360 case NULL: 361 if (!value.constantTypeKind().equals(kind)) { 362 throw typeError(position, value, kind); 363 } 364 return value; 365 } 366 throw new AssertionError(kind); 367 } 368 asBoolean(int position, Value value)369 private Const.BooleanValue asBoolean(int position, Value value) { 370 if (!value.constantTypeKind().equals(TurbineConstantTypeKind.BOOLEAN)) { 371 throw typeError(position, value, TurbineConstantTypeKind.BOOLEAN); 372 } 373 return (Const.BooleanValue) value; 374 } 375 asString(int position, Value value)376 private Const.StringValue asString(int position, Value value) { 377 if (!value.constantTypeKind().equals(TurbineConstantTypeKind.STRING)) { 378 throw typeError(position, value, TurbineConstantTypeKind.STRING); 379 } 380 return (Const.StringValue) value; 381 } 382 toString(int position, Value value)383 private Const.StringValue toString(int position, Value value) { 384 String result; 385 switch (value.constantTypeKind()) { 386 case CHAR: 387 result = String.valueOf(((Const.CharValue) value).value()); 388 break; 389 case SHORT: 390 result = String.valueOf(((Const.ShortValue) value).value()); 391 break; 392 case INT: 393 result = String.valueOf(((Const.IntValue) value).value()); 394 break; 395 case LONG: 396 result = String.valueOf(((Const.LongValue) value).value()); 397 break; 398 case FLOAT: 399 result = String.valueOf(((Const.FloatValue) value).value()); 400 break; 401 case DOUBLE: 402 result = String.valueOf(((Const.DoubleValue) value).value()); 403 break; 404 case BOOLEAN: 405 result = String.valueOf(((Const.BooleanValue) value).value()); 406 break; 407 case BYTE: 408 result = String.valueOf(((Const.ByteValue) value).value()); 409 break; 410 case STRING: 411 return (StringValue) value; 412 default: 413 throw typeError(position, value, TurbineConstantTypeKind.STRING); 414 } 415 return new Const.StringValue(result); 416 } 417 asChar(int position, Value value)418 private Const.CharValue asChar(int position, Value value) { 419 char result; 420 switch (value.constantTypeKind()) { 421 case CHAR: 422 return (Const.CharValue) value; 423 case BYTE: 424 result = (char) ((Const.ByteValue) value).value(); 425 break; 426 case SHORT: 427 result = (char) ((Const.ShortValue) value).value(); 428 break; 429 case INT: 430 result = (char) ((Const.IntValue) value).value(); 431 break; 432 case LONG: 433 result = (char) ((Const.LongValue) value).value(); 434 break; 435 case FLOAT: 436 result = (char) ((Const.FloatValue) value).value(); 437 break; 438 case DOUBLE: 439 result = (char) ((Const.DoubleValue) value).value(); 440 break; 441 default: 442 throw typeError(position, value, TurbineConstantTypeKind.CHAR); 443 } 444 return new Const.CharValue(result); 445 } 446 asByte(int position, Value value)447 private Const.ByteValue asByte(int position, Value value) { 448 byte result; 449 switch (value.constantTypeKind()) { 450 case CHAR: 451 result = (byte) ((Const.CharValue) value).value(); 452 break; 453 case BYTE: 454 return (Const.ByteValue) value; 455 case SHORT: 456 result = (byte) ((Const.ShortValue) value).value(); 457 break; 458 case INT: 459 result = (byte) ((Const.IntValue) value).value(); 460 break; 461 case LONG: 462 result = (byte) ((Const.LongValue) value).value(); 463 break; 464 case FLOAT: 465 result = (byte) ((Const.FloatValue) value).value(); 466 break; 467 case DOUBLE: 468 result = (byte) ((Const.DoubleValue) value).value(); 469 break; 470 default: 471 throw typeError(position, value, TurbineConstantTypeKind.BYTE); 472 } 473 return new Const.ByteValue(result); 474 } 475 asShort(int position, Value value)476 private Const.ShortValue asShort(int position, Value value) { 477 short result; 478 switch (value.constantTypeKind()) { 479 case CHAR: 480 result = (short) ((Const.CharValue) value).value(); 481 break; 482 case BYTE: 483 result = ((Const.ByteValue) value).value(); 484 break; 485 case SHORT: 486 return (Const.ShortValue) value; 487 case INT: 488 result = (short) ((Const.IntValue) value).value(); 489 break; 490 case LONG: 491 result = (short) ((Const.LongValue) value).value(); 492 break; 493 case FLOAT: 494 result = (short) ((Const.FloatValue) value).value(); 495 break; 496 case DOUBLE: 497 result = (short) ((Const.DoubleValue) value).value(); 498 break; 499 default: 500 throw typeError(position, value, TurbineConstantTypeKind.SHORT); 501 } 502 return new Const.ShortValue(result); 503 } 504 asInt(int position, Value value)505 private Const.IntValue asInt(int position, Value value) { 506 int result; 507 switch (value.constantTypeKind()) { 508 case CHAR: 509 result = ((CharValue) value).value(); 510 break; 511 case BYTE: 512 result = ((Const.ByteValue) value).value(); 513 break; 514 case SHORT: 515 result = ((Const.ShortValue) value).value(); 516 break; 517 case INT: 518 return (Const.IntValue) value; 519 case LONG: 520 result = (int) ((Const.LongValue) value).value(); 521 break; 522 case FLOAT: 523 result = (int) ((Const.FloatValue) value).value(); 524 break; 525 case DOUBLE: 526 result = (int) ((Const.DoubleValue) value).value(); 527 break; 528 default: 529 throw typeError(position, value, TurbineConstantTypeKind.INT); 530 } 531 return new Const.IntValue(result); 532 } 533 asLong(int position, Value value)534 private Const.LongValue asLong(int position, Value value) { 535 long result; 536 switch (value.constantTypeKind()) { 537 case CHAR: 538 result = ((CharValue) value).value(); 539 break; 540 case BYTE: 541 result = ((Const.ByteValue) value).value(); 542 break; 543 case SHORT: 544 result = ((Const.ShortValue) value).value(); 545 break; 546 case INT: 547 result = ((Const.IntValue) value).value(); 548 break; 549 case LONG: 550 return (Const.LongValue) value; 551 case FLOAT: 552 result = (long) ((Const.FloatValue) value).value(); 553 break; 554 case DOUBLE: 555 result = (long) ((Const.DoubleValue) value).value(); 556 break; 557 default: 558 throw typeError(position, value, TurbineConstantTypeKind.LONG); 559 } 560 return new Const.LongValue(result); 561 } 562 asFloat(int position, Value value)563 private Const.FloatValue asFloat(int position, Value value) { 564 float result; 565 switch (value.constantTypeKind()) { 566 case CHAR: 567 result = ((CharValue) value).value(); 568 break; 569 case BYTE: 570 result = ((Const.ByteValue) value).value(); 571 break; 572 case SHORT: 573 result = ((Const.ShortValue) value).value(); 574 break; 575 case INT: 576 result = (float) ((Const.IntValue) value).value(); 577 break; 578 case LONG: 579 result = (float) ((Const.LongValue) value).value(); 580 break; 581 case FLOAT: 582 return (FloatValue) value; 583 case DOUBLE: 584 result = (float) ((Const.DoubleValue) value).value(); 585 break; 586 default: 587 throw typeError(position, value, TurbineConstantTypeKind.FLOAT); 588 } 589 return new Const.FloatValue(result); 590 } 591 asDouble(int position, Value value)592 private Const.DoubleValue asDouble(int position, Value value) { 593 double result; 594 switch (value.constantTypeKind()) { 595 case CHAR: 596 result = ((CharValue) value).value(); 597 break; 598 case BYTE: 599 result = ((Const.ByteValue) value).value(); 600 break; 601 case SHORT: 602 result = ((Const.ShortValue) value).value(); 603 break; 604 case INT: 605 result = ((Const.IntValue) value).value(); 606 break; 607 case LONG: 608 result = (double) ((Const.LongValue) value).value(); 609 break; 610 case FLOAT: 611 result = ((Const.FloatValue) value).value(); 612 break; 613 case DOUBLE: 614 return (DoubleValue) value; 615 default: 616 throw typeError(position, value, TurbineConstantTypeKind.DOUBLE); 617 } 618 return new Const.DoubleValue(result); 619 } 620 evalValue(Expression tree)621 private @Nullable Value evalValue(Expression tree) { 622 Const result = eval(tree); 623 // TODO(cushon): consider distinguishing between constant field and annotation values, 624 // and only allowing class literals / enum constants in the latter 625 return (result instanceof Value) ? (Value) result : null; 626 } 627 evalConditional(Conditional t)628 private @Nullable Value evalConditional(Conditional t) { 629 Value condition = evalValue(t.cond()); 630 if (condition == null) { 631 return null; 632 } 633 return asBoolean(t.position(), condition).value() 634 ? evalValue(t.iftrue()) 635 : evalValue(t.iffalse()); 636 } 637 evalUnary(Unary t)638 private @Nullable Value evalUnary(Unary t) { 639 Value expr = evalValue(t.expr()); 640 if (expr == null) { 641 return null; 642 } 643 switch (t.op()) { 644 case NOT: 645 return unaryNegate(t.position(), expr); 646 case BITWISE_COMP: 647 return bitwiseComp(t.position(), expr); 648 case UNARY_PLUS: 649 return unaryPlus(t.position(), expr); 650 case NEG: 651 return unaryMinus(t.position(), expr); 652 default: 653 throw new AssertionError(t.op()); 654 } 655 } 656 unaryNegate(int position, Value expr)657 private @Nullable Value unaryNegate(int position, Value expr) { 658 switch (expr.constantTypeKind()) { 659 case BOOLEAN: 660 return new Const.BooleanValue(!asBoolean(position, expr).value()); 661 default: 662 throw error(position, ErrorKind.OPERAND_TYPE, expr.constantTypeKind()); 663 } 664 } 665 bitwiseComp(int position, Value expr)666 private @Nullable Value bitwiseComp(int position, Value expr) { 667 expr = promoteUnary(position, expr); 668 switch (expr.constantTypeKind()) { 669 case INT: 670 return new Const.IntValue(~asInt(position, expr).value()); 671 case LONG: 672 return new Const.LongValue(~asLong(position, expr).value()); 673 default: 674 throw error(position, ErrorKind.OPERAND_TYPE, expr.constantTypeKind()); 675 } 676 } 677 unaryPlus(int position, Value expr)678 private @Nullable Value unaryPlus(int position, Value expr) { 679 expr = promoteUnary(position, expr); 680 switch (expr.constantTypeKind()) { 681 case INT: 682 return new Const.IntValue(+asInt(position, expr).value()); 683 case LONG: 684 return new Const.LongValue(+asLong(position, expr).value()); 685 case FLOAT: 686 return new Const.FloatValue(+asFloat(position, expr).value()); 687 case DOUBLE: 688 return new Const.DoubleValue(+asDouble(position, expr).value()); 689 default: 690 throw error(position, ErrorKind.OPERAND_TYPE, expr.constantTypeKind()); 691 } 692 } 693 unaryMinus(int position, Value expr)694 private @Nullable Value unaryMinus(int position, Value expr) { 695 expr = promoteUnary(position, expr); 696 switch (expr.constantTypeKind()) { 697 case INT: 698 return new Const.IntValue(-asInt(position, expr).value()); 699 case LONG: 700 return new Const.LongValue(-asLong(position, expr).value()); 701 case FLOAT: 702 return new Const.FloatValue(-asFloat(position, expr).value()); 703 case DOUBLE: 704 return new Const.DoubleValue(-asDouble(position, expr).value()); 705 default: 706 throw error(position, ErrorKind.OPERAND_TYPE, expr.constantTypeKind()); 707 } 708 } 709 evalCast(TypeCast t)710 private @Nullable Value evalCast(TypeCast t) { 711 Value expr = evalValue(t.expr()); 712 if (expr == null) { 713 return null; 714 } 715 switch (t.ty().kind()) { 716 case PRIM_TY: 717 return coerce(t.expr().position(), expr, ((Tree.PrimTy) t.ty()).tykind()); 718 case CLASS_TY: 719 { 720 ClassTy classTy = (ClassTy) t.ty(); 721 // TODO(cushon): check package? 722 if (!classTy.name().value().equals("String")) { 723 // Explicit boxing cases (e.g. `(Boolean) false`) are legal, but not const exprs. 724 return null; 725 } 726 return toString(t.expr().position(), expr); 727 } 728 default: 729 throw new AssertionError(t.ty().kind()); 730 } 731 } 732 add(int position, Value a, Value b)733 private @Nullable Value add(int position, Value a, Value b) { 734 if (a.constantTypeKind() == TurbineConstantTypeKind.STRING 735 || b.constantTypeKind() == TurbineConstantTypeKind.STRING) { 736 return new Const.StringValue(toString(position, a).value() + toString(position, b).value()); 737 } 738 TurbineConstantTypeKind type = promoteBinary(position, a, b); 739 a = coerce(position, a, type); 740 b = coerce(position, b, type); 741 switch (type) { 742 case INT: 743 return new Const.IntValue(asInt(position, a).value() + asInt(position, b).value()); 744 case LONG: 745 return new Const.LongValue(asLong(position, a).value() + asLong(position, b).value()); 746 case FLOAT: 747 return new Const.FloatValue(asFloat(position, a).value() + asFloat(position, b).value()); 748 case DOUBLE: 749 return new Const.DoubleValue(asDouble(position, a).value() + asDouble(position, b).value()); 750 default: 751 throw error(position, ErrorKind.OPERAND_TYPE, type); 752 } 753 } 754 subtract(int position, Value a, Value b)755 private @Nullable Value subtract(int position, Value a, Value b) { 756 TurbineConstantTypeKind type = promoteBinary(position, a, b); 757 a = coerce(position, a, type); 758 b = coerce(position, b, type); 759 switch (type) { 760 case INT: 761 return new Const.IntValue(asInt(position, a).value() - asInt(position, b).value()); 762 case LONG: 763 return new Const.LongValue(asLong(position, a).value() - asLong(position, b).value()); 764 case FLOAT: 765 return new Const.FloatValue(asFloat(position, a).value() - asFloat(position, b).value()); 766 case DOUBLE: 767 return new Const.DoubleValue(asDouble(position, a).value() - asDouble(position, b).value()); 768 default: 769 throw error(position, ErrorKind.OPERAND_TYPE, type); 770 } 771 } 772 mult(int position, Value a, Value b)773 private @Nullable Value mult(int position, Value a, Value b) { 774 TurbineConstantTypeKind type = promoteBinary(position, a, b); 775 a = coerce(position, a, type); 776 b = coerce(position, b, type); 777 switch (type) { 778 case INT: 779 return new Const.IntValue(asInt(position, a).value() * asInt(position, b).value()); 780 case LONG: 781 return new Const.LongValue(asLong(position, a).value() * asLong(position, b).value()); 782 case FLOAT: 783 return new Const.FloatValue(asFloat(position, a).value() * asFloat(position, b).value()); 784 case DOUBLE: 785 return new Const.DoubleValue(asDouble(position, a).value() * asDouble(position, b).value()); 786 default: 787 throw error(position, ErrorKind.OPERAND_TYPE, type); 788 } 789 } 790 divide(int position, Value a, Value b)791 private @Nullable Value divide(int position, Value a, Value b) { 792 TurbineConstantTypeKind type = promoteBinary(position, a, b); 793 a = coerce(position, a, type); 794 b = coerce(position, b, type); 795 switch (type) { 796 case INT: 797 return new Const.IntValue(asInt(position, a).value() / asInt(position, b).value()); 798 case LONG: 799 return new Const.LongValue(asLong(position, a).value() / asLong(position, b).value()); 800 case FLOAT: 801 return new Const.FloatValue(asFloat(position, a).value() / asFloat(position, b).value()); 802 case DOUBLE: 803 return new Const.DoubleValue(asDouble(position, a).value() / asDouble(position, b).value()); 804 default: 805 throw error(position, ErrorKind.OPERAND_TYPE, type); 806 } 807 } 808 mod(int position, Value a, Value b)809 private @Nullable Value mod(int position, Value a, Value b) { 810 TurbineConstantTypeKind type = promoteBinary(position, a, b); 811 a = coerce(position, a, type); 812 b = coerce(position, b, type); 813 switch (type) { 814 case INT: 815 return new Const.IntValue(asInt(position, a).value() % asInt(position, b).value()); 816 case LONG: 817 return new Const.LongValue(asLong(position, a).value() % asLong(position, b).value()); 818 case FLOAT: 819 return new Const.FloatValue(asFloat(position, a).value() % asFloat(position, b).value()); 820 case DOUBLE: 821 return new Const.DoubleValue(asDouble(position, a).value() % asDouble(position, b).value()); 822 default: 823 throw error(position, ErrorKind.OPERAND_TYPE, type); 824 } 825 } 826 827 private static final int INT_SHIFT_MASK = 0b11111; 828 829 private static final int LONG_SHIFT_MASK = 0b111111; 830 shiftLeft(int position, Value a, Value b)831 private @Nullable Value shiftLeft(int position, Value a, Value b) { 832 a = promoteUnary(position, a); 833 b = promoteUnary(position, b); 834 switch (a.constantTypeKind()) { 835 case INT: 836 return new Const.IntValue( 837 asInt(position, a).value() << (asInt(position, b).value() & INT_SHIFT_MASK)); 838 case LONG: 839 return new Const.LongValue( 840 asLong(position, a).value() << (asInt(position, b).value() & LONG_SHIFT_MASK)); 841 default: 842 throw error(position, ErrorKind.OPERAND_TYPE, a.constantTypeKind()); 843 } 844 } 845 shiftRight(int position, Value a, Value b)846 private @Nullable Value shiftRight(int position, Value a, Value b) { 847 a = promoteUnary(position, a); 848 b = promoteUnary(position, b); 849 switch (a.constantTypeKind()) { 850 case INT: 851 return new Const.IntValue( 852 asInt(position, a).value() >> (asInt(position, b).value() & INT_SHIFT_MASK)); 853 case LONG: 854 return new Const.LongValue( 855 asLong(position, a).value() >> (asInt(position, b).value() & LONG_SHIFT_MASK)); 856 default: 857 throw error(position, ErrorKind.OPERAND_TYPE, a.constantTypeKind()); 858 } 859 } 860 unsignedShiftRight(int position, Value a, Value b)861 private @Nullable Value unsignedShiftRight(int position, Value a, Value b) { 862 a = promoteUnary(position, a); 863 b = promoteUnary(position, b); 864 switch (a.constantTypeKind()) { 865 case INT: 866 return new Const.IntValue( 867 asInt(position, a).value() >>> (asInt(position, b).value() & INT_SHIFT_MASK)); 868 case LONG: 869 return new Const.LongValue( 870 asLong(position, a).value() >>> (asInt(position, b).value() & LONG_SHIFT_MASK)); 871 default: 872 throw error(position, ErrorKind.OPERAND_TYPE, a.constantTypeKind()); 873 } 874 } 875 lessThan(int position, Value a, Value b)876 private @Nullable Value lessThan(int position, Value a, Value b) { 877 TurbineConstantTypeKind type = promoteBinary(position, a, b); 878 a = coerce(position, a, type); 879 b = coerce(position, b, type); 880 switch (type) { 881 case INT: 882 return new Const.BooleanValue(asInt(position, a).value() < asInt(position, b).value()); 883 case LONG: 884 return new Const.BooleanValue(asLong(position, a).value() < asLong(position, b).value()); 885 case FLOAT: 886 return new Const.BooleanValue(asFloat(position, a).value() < asFloat(position, b).value()); 887 case DOUBLE: 888 return new Const.BooleanValue( 889 asDouble(position, a).value() < asDouble(position, b).value()); 890 default: 891 throw error(position, ErrorKind.OPERAND_TYPE, type); 892 } 893 } 894 lessThanEqual(int position, Value a, Value b)895 private @Nullable Value lessThanEqual(int position, Value a, Value b) { 896 TurbineConstantTypeKind type = promoteBinary(position, a, b); 897 a = coerce(position, a, type); 898 b = coerce(position, b, type); 899 switch (type) { 900 case INT: 901 return new Const.BooleanValue(asInt(position, a).value() <= asInt(position, b).value()); 902 case LONG: 903 return new Const.BooleanValue(asLong(position, a).value() <= asLong(position, b).value()); 904 case FLOAT: 905 return new Const.BooleanValue(asFloat(position, a).value() <= asFloat(position, b).value()); 906 case DOUBLE: 907 return new Const.BooleanValue( 908 asDouble(position, a).value() <= asDouble(position, b).value()); 909 default: 910 throw error(position, ErrorKind.OPERAND_TYPE, type); 911 } 912 } 913 greaterThan(int position, Value a, Value b)914 private @Nullable Value greaterThan(int position, Value a, Value b) { 915 TurbineConstantTypeKind type = promoteBinary(position, a, b); 916 a = coerce(position, a, type); 917 b = coerce(position, b, type); 918 switch (type) { 919 case INT: 920 return new Const.BooleanValue(asInt(position, a).value() > asInt(position, b).value()); 921 case LONG: 922 return new Const.BooleanValue(asLong(position, a).value() > asLong(position, b).value()); 923 case FLOAT: 924 return new Const.BooleanValue(asFloat(position, a).value() > asFloat(position, b).value()); 925 case DOUBLE: 926 return new Const.BooleanValue( 927 asDouble(position, a).value() > asDouble(position, b).value()); 928 default: 929 throw error(position, ErrorKind.OPERAND_TYPE, type); 930 } 931 } 932 greaterThanEqual(int position, Value a, Value b)933 private @Nullable Value greaterThanEqual(int position, Value a, Value b) { 934 TurbineConstantTypeKind type = promoteBinary(position, a, b); 935 a = coerce(position, a, type); 936 b = coerce(position, b, type); 937 switch (type) { 938 case INT: 939 return new Const.BooleanValue(asInt(position, a).value() >= asInt(position, b).value()); 940 case LONG: 941 return new Const.BooleanValue(asLong(position, a).value() >= asLong(position, b).value()); 942 case FLOAT: 943 return new Const.BooleanValue(asFloat(position, a).value() >= asFloat(position, b).value()); 944 case DOUBLE: 945 return new Const.BooleanValue( 946 asDouble(position, a).value() >= asDouble(position, b).value()); 947 default: 948 throw error(position, ErrorKind.OPERAND_TYPE, type); 949 } 950 } 951 equal(int position, Value a, Value b)952 private @Nullable Value equal(int position, Value a, Value b) { 953 switch (a.constantTypeKind()) { 954 case STRING: 955 return new Const.BooleanValue( 956 asString(position, a).value().equals(asString(position, b).value())); 957 case BOOLEAN: 958 return new Const.BooleanValue( 959 asBoolean(position, a).value() == asBoolean(position, b).value()); 960 default: 961 break; 962 } 963 TurbineConstantTypeKind type = promoteBinary(position, a, b); 964 a = coerce(position, a, type); 965 b = coerce(position, b, type); 966 switch (type) { 967 case INT: 968 return new Const.BooleanValue(asInt(position, a).value() == asInt(position, b).value()); 969 case LONG: 970 return new Const.BooleanValue(asLong(position, a).value() == asLong(position, b).value()); 971 case FLOAT: 972 return new Const.BooleanValue(asFloat(position, a).value() == asFloat(position, b).value()); 973 case DOUBLE: 974 return new Const.BooleanValue( 975 asDouble(position, a).value() == asDouble(position, b).value()); 976 default: 977 throw error(position, ErrorKind.OPERAND_TYPE, type); 978 } 979 } 980 notEqual(int position, Value a, Value b)981 private @Nullable Value notEqual(int position, Value a, Value b) { 982 switch (a.constantTypeKind()) { 983 case STRING: 984 return new Const.BooleanValue( 985 !asString(position, a).value().equals(asString(position, b).value())); 986 case BOOLEAN: 987 return new Const.BooleanValue( 988 asBoolean(position, a).value() != asBoolean(position, b).value()); 989 default: 990 break; 991 } 992 TurbineConstantTypeKind type = promoteBinary(position, a, b); 993 a = coerce(position, a, type); 994 b = coerce(position, b, type); 995 switch (type) { 996 case INT: 997 return new Const.BooleanValue(asInt(position, a).value() != asInt(position, b).value()); 998 case LONG: 999 return new Const.BooleanValue(asLong(position, a).value() != asLong(position, b).value()); 1000 case FLOAT: 1001 return new Const.BooleanValue(asFloat(position, a).value() != asFloat(position, b).value()); 1002 case DOUBLE: 1003 return new Const.BooleanValue( 1004 asDouble(position, a).value() != asDouble(position, b).value()); 1005 default: 1006 throw error(position, ErrorKind.OPERAND_TYPE, type); 1007 } 1008 } 1009 bitwiseAnd(int position, Value a, Value b)1010 private Value bitwiseAnd(int position, Value a, Value b) { 1011 switch (a.constantTypeKind()) { 1012 case BOOLEAN: 1013 return new Const.BooleanValue( 1014 asBoolean(position, a).value() & asBoolean(position, b).value()); 1015 default: 1016 break; 1017 } 1018 TurbineConstantTypeKind type = promoteBinary(position, a, b); 1019 a = coerce(position, a, type); 1020 b = coerce(position, b, type); 1021 switch (type) { 1022 case INT: 1023 return new Const.IntValue(asInt(position, a).value() & asInt(position, b).value()); 1024 case LONG: 1025 return new Const.LongValue(asLong(position, a).value() & asLong(position, b).value()); 1026 default: 1027 throw error(position, ErrorKind.OPERAND_TYPE, type); 1028 } 1029 } 1030 bitwiseOr(int position, Value a, Value b)1031 private Value bitwiseOr(int position, Value a, Value b) { 1032 switch (a.constantTypeKind()) { 1033 case BOOLEAN: 1034 return new Const.BooleanValue( 1035 asBoolean(position, a).value() | asBoolean(position, b).value()); 1036 default: 1037 break; 1038 } 1039 TurbineConstantTypeKind type = promoteBinary(position, a, b); 1040 a = coerce(position, a, type); 1041 b = coerce(position, b, type); 1042 switch (type) { 1043 case INT: 1044 return new Const.IntValue(asInt(position, a).value() | asInt(position, b).value()); 1045 case LONG: 1046 return new Const.LongValue(asLong(position, a).value() | asLong(position, b).value()); 1047 default: 1048 throw error(position, ErrorKind.OPERAND_TYPE, type); 1049 } 1050 } 1051 bitwiseXor(int position, Value a, Value b)1052 private @Nullable Value bitwiseXor(int position, Value a, Value b) { 1053 switch (a.constantTypeKind()) { 1054 case BOOLEAN: 1055 return new Const.BooleanValue( 1056 asBoolean(position, a).value() ^ asBoolean(position, b).value()); 1057 default: 1058 break; 1059 } 1060 TurbineConstantTypeKind type = promoteBinary(position, a, b); 1061 a = coerce(position, a, type); 1062 b = coerce(position, b, type); 1063 switch (type) { 1064 case INT: 1065 return new Const.IntValue(asInt(position, a).value() ^ asInt(position, b).value()); 1066 case LONG: 1067 return new Const.LongValue(asLong(position, a).value() ^ asLong(position, b).value()); 1068 default: 1069 throw error(position, ErrorKind.OPERAND_TYPE, type); 1070 } 1071 } 1072 evalBinary(Binary t)1073 private @Nullable Value evalBinary(Binary t) { 1074 Value result = null; 1075 boolean first = true; 1076 for (Expression child : t.children()) { 1077 Value value = evalValue(child); 1078 if (value == null) { 1079 return null; 1080 } 1081 if (first) { 1082 result = value; 1083 } else { 1084 result = evalBinary(child.position(), t.op(), requireNonNull(result), value); 1085 } 1086 first = false; 1087 } 1088 return result; 1089 } 1090 evalBinary(int position, TurbineOperatorKind op, Value lhs, Value rhs)1091 private @Nullable Value evalBinary(int position, TurbineOperatorKind op, Value lhs, Value rhs) { 1092 switch (op) { 1093 case PLUS: 1094 return add(position, lhs, rhs); 1095 case MINUS: 1096 return subtract(position, lhs, rhs); 1097 case MULT: 1098 return mult(position, lhs, rhs); 1099 case DIVIDE: 1100 return divide(position, lhs, rhs); 1101 case MODULO: 1102 return mod(position, lhs, rhs); 1103 case SHIFT_LEFT: 1104 return shiftLeft(position, lhs, rhs); 1105 case SHIFT_RIGHT: 1106 return shiftRight(position, lhs, rhs); 1107 case UNSIGNED_SHIFT_RIGHT: 1108 return unsignedShiftRight(position, lhs, rhs); 1109 case LESS_THAN: 1110 return lessThan(position, lhs, rhs); 1111 case GREATER_THAN: 1112 return greaterThan(position, lhs, rhs); 1113 case LESS_THAN_EQ: 1114 return lessThanEqual(position, lhs, rhs); 1115 case GREATER_THAN_EQ: 1116 return greaterThanEqual(position, lhs, rhs); 1117 case EQUAL: 1118 return equal(position, lhs, rhs); 1119 case NOT_EQUAL: 1120 return notEqual(position, lhs, rhs); 1121 case AND: 1122 return new Const.BooleanValue( 1123 asBoolean(position, lhs).value() && asBoolean(position, rhs).value()); 1124 case OR: 1125 return new Const.BooleanValue( 1126 asBoolean(position, lhs).value() || asBoolean(position, rhs).value()); 1127 case BITWISE_AND: 1128 return bitwiseAnd(position, lhs, rhs); 1129 case BITWISE_XOR: 1130 return bitwiseXor(position, lhs, rhs); 1131 case BITWISE_OR: 1132 return bitwiseOr(position, lhs, rhs); 1133 default: 1134 throw new AssertionError(op); 1135 } 1136 } 1137 promoteUnary(int position, Value v)1138 private Value promoteUnary(int position, Value v) { 1139 switch (v.constantTypeKind()) { 1140 case CHAR: 1141 case SHORT: 1142 case BYTE: 1143 return asInt(position, v); 1144 case INT: 1145 case LONG: 1146 case FLOAT: 1147 case DOUBLE: 1148 return v; 1149 default: 1150 throw error(position, ErrorKind.OPERAND_TYPE, v.constantTypeKind()); 1151 } 1152 } 1153 promoteBinary(int position, Value a, Value b)1154 private TurbineConstantTypeKind promoteBinary(int position, Value a, Value b) { 1155 a = promoteUnary(position, a); 1156 b = promoteUnary(position, b); 1157 switch (a.constantTypeKind()) { 1158 case INT: 1159 switch (b.constantTypeKind()) { 1160 case INT: 1161 case LONG: 1162 case DOUBLE: 1163 case FLOAT: 1164 return b.constantTypeKind(); 1165 default: 1166 throw error(position, ErrorKind.OPERAND_TYPE, b.constantTypeKind()); 1167 } 1168 case LONG: 1169 switch (b.constantTypeKind()) { 1170 case INT: 1171 return TurbineConstantTypeKind.LONG; 1172 case LONG: 1173 case DOUBLE: 1174 case FLOAT: 1175 return b.constantTypeKind(); 1176 default: 1177 throw error(position, ErrorKind.OPERAND_TYPE, b.constantTypeKind()); 1178 } 1179 case FLOAT: 1180 switch (b.constantTypeKind()) { 1181 case INT: 1182 case LONG: 1183 case FLOAT: 1184 return TurbineConstantTypeKind.FLOAT; 1185 case DOUBLE: 1186 return TurbineConstantTypeKind.DOUBLE; 1187 default: 1188 throw error(position, ErrorKind.OPERAND_TYPE, b.constantTypeKind()); 1189 } 1190 case DOUBLE: 1191 switch (b.constantTypeKind()) { 1192 case INT: 1193 case LONG: 1194 case FLOAT: 1195 case DOUBLE: 1196 return TurbineConstantTypeKind.DOUBLE; 1197 default: 1198 throw error(position, ErrorKind.OPERAND_TYPE, b.constantTypeKind()); 1199 } 1200 default: 1201 throw error(position, ErrorKind.OPERAND_TYPE, a.constantTypeKind()); 1202 } 1203 } 1204 evaluateAnnotations(ImmutableList<AnnoInfo> annotations)1205 ImmutableList<AnnoInfo> evaluateAnnotations(ImmutableList<AnnoInfo> annotations) { 1206 ImmutableList.Builder<AnnoInfo> result = ImmutableList.builder(); 1207 for (AnnoInfo annotation : annotations) { 1208 result.add(evaluateAnnotation(annotation)); 1209 } 1210 return result.build(); 1211 } 1212 1213 /** 1214 * Evaluates annotation arguments given the symbol of the annotation declaration and a list of 1215 * expression trees. 1216 */ evaluateAnnotation(AnnoInfo info)1217 AnnoInfo evaluateAnnotation(AnnoInfo info) { 1218 // bail if annotation has not been resolved 1219 if (info.sym() == null) { 1220 return info; 1221 } 1222 TypeBoundClass annoClass = env.getNonNull(info.sym()); 1223 if (annoClass.kind() != TurbineTyKind.ANNOTATION) { 1224 // we've already reported an error for non-annotation symbols used as annotations, 1225 // skip error handling for annotation arguments 1226 return info; 1227 } 1228 Map<String, MethodInfo> template = new LinkedHashMap<>(); 1229 if (annoClass != null) { 1230 for (MethodInfo method : annoClass.methods()) { 1231 template.put(method.name(), method); 1232 } 1233 } 1234 1235 Map<String, Const> values = new LinkedHashMap<>(); 1236 for (Expression arg : info.args()) { 1237 Expression expr; 1238 String key; 1239 if (arg.kind() == Tree.Kind.ASSIGN) { 1240 Tree.Assign assign = (Tree.Assign) arg; 1241 key = assign.name().value(); 1242 expr = assign.expr(); 1243 } else { 1244 if (info.args().size() != 1) { 1245 throw error(arg.position(), ErrorKind.ANNOTATION_VALUE_NAME); 1246 } 1247 // expand the implicit 'value' name; `@Foo(42)` is sugar for `@Foo(value=42)` 1248 key = "value"; 1249 expr = arg; 1250 } 1251 MethodInfo methodInfo = template.remove(key); 1252 if (methodInfo == null) { 1253 log.error( 1254 arg.position(), 1255 ErrorKind.CANNOT_RESOLVE, 1256 String.format("element %s() in %s", key, info.sym())); 1257 continue; 1258 } 1259 Const value = evalAnnotationValue(expr, methodInfo.returnType()); 1260 if (value == null) { 1261 log.error(expr.position(), ErrorKind.EXPRESSION_ERROR); 1262 continue; 1263 } 1264 Const existing = values.put(key, value); 1265 if (existing != null) { 1266 log.error(arg.position(), ErrorKind.INVALID_ANNOTATION_ARGUMENT); 1267 continue; 1268 } 1269 } 1270 for (MethodInfo methodInfo : template.values()) { 1271 if (!methodInfo.hasDefaultValue()) { 1272 throw error( 1273 info.tree().position(), ErrorKind.MISSING_ANNOTATION_ARGUMENT, methodInfo.name()); 1274 } 1275 } 1276 return info.withValues(ImmutableMap.copyOf(values)); 1277 } 1278 evalAnno(Tree.Anno t)1279 private @Nullable TurbineAnnotationValue evalAnno(Tree.Anno t) { 1280 LookupResult result = scope.lookup(new LookupKey(t.name())); 1281 if (result == null) { 1282 log.error( 1283 t.name().get(0).position(), ErrorKind.CANNOT_RESOLVE, Joiner.on(".").join(t.name())); 1284 return null; 1285 } 1286 ClassSymbol sym = (ClassSymbol) result.sym(); 1287 for (Ident name : result.remaining()) { 1288 sym = Resolve.resolve(env, sym, sym, name); 1289 if (sym == null) { 1290 throw error(name.position(), ErrorKind.CANNOT_RESOLVE, name.value()); 1291 } 1292 } 1293 if (sym == null) { 1294 return null; 1295 } 1296 if (env.getNonNull(sym).kind() != TurbineTyKind.ANNOTATION) { 1297 log.error(t.position(), ErrorKind.NOT_AN_ANNOTATION, sym); 1298 } 1299 AnnoInfo annoInfo = evaluateAnnotation(new AnnoInfo(source, sym, t, ImmutableMap.of())); 1300 return new TurbineAnnotationValue(annoInfo); 1301 } 1302 evalArrayInit(ArrayInit t)1303 private @Nullable ArrayInitValue evalArrayInit(ArrayInit t) { 1304 ImmutableList.Builder<Const> elements = ImmutableList.builder(); 1305 for (Expression e : t.exprs()) { 1306 Const arg = eval(e); 1307 if (arg == null) { 1308 return null; 1309 } 1310 elements.add(arg); 1311 } 1312 return new Const.ArrayInitValue(elements.build()); 1313 } 1314 evalAnnotationValue(Tree tree, Type ty)1315 @Nullable Const evalAnnotationValue(Tree tree, Type ty) { 1316 if (ty == null) { 1317 throw error(tree.position(), ErrorKind.EXPRESSION_ERROR); 1318 } 1319 Const value = eval(tree); 1320 if (value == null) { 1321 log.error(tree.position(), ErrorKind.EXPRESSION_ERROR); 1322 return null; 1323 } 1324 switch (ty.tyKind()) { 1325 case PRIM_TY: 1326 if (!(value instanceof Value)) { 1327 throw error(tree.position(), ErrorKind.EXPRESSION_ERROR); 1328 } 1329 return coerce(tree.position(), (Value) value, ((Type.PrimTy) ty).primkind()); 1330 case CLASS_TY: 1331 case TY_VAR: 1332 return value; 1333 case ARRAY_TY: 1334 { 1335 Type elementType = ((Type.ArrayTy) ty).elementType(); 1336 ImmutableList<Const> elements = 1337 value.kind() == Const.Kind.ARRAY 1338 ? ((Const.ArrayInitValue) value).elements() 1339 : ImmutableList.of(value); 1340 ImmutableList.Builder<Const> coerced = ImmutableList.builder(); 1341 for (Const element : elements) { 1342 coerced.add(cast(tree.position(), elementType, element)); 1343 } 1344 return new Const.ArrayInitValue(coerced.build()); 1345 } 1346 default: 1347 throw new AssertionError(ty.tyKind()); 1348 } 1349 } 1350 error(int position, ErrorKind kind, Object... args)1351 private TurbineError error(int position, ErrorKind kind, Object... args) { 1352 return TurbineError.format(source, position, kind, args); 1353 } 1354 typeError(int position, Value value, TurbineConstantTypeKind kind)1355 private TurbineError typeError(int position, Value value, TurbineConstantTypeKind kind) { 1356 return error(position, ErrorKind.TYPE_CONVERSION, value, value.constantTypeKind(), kind); 1357 } 1358 evalFieldInitializer(Expression expression, Type type)1359 public @Nullable Value evalFieldInitializer(Expression expression, Type type) { 1360 try { 1361 Const value = eval(expression); 1362 if (value == null || value.kind() != Const.Kind.PRIMITIVE) { 1363 return null; 1364 } 1365 return (Value) cast(expression.position(), type, value); 1366 } catch (TurbineError error) { 1367 for (TurbineDiagnostic diagnostic : error.diagnostics()) { 1368 switch (diagnostic.kind()) { 1369 case CANNOT_RESOLVE: 1370 // assume this wasn't a constant 1371 return null; 1372 default: // fall out 1373 } 1374 } 1375 throw error; 1376 } catch (ConstCastError error) { 1377 return null; 1378 } 1379 } 1380 } 1381