ConstEvaluator.java revision 5bd34220e797da6446ba3f69aae9d62023171a9e
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; 20import static com.google.common.base.Verify.verifyNotNull; 21 22import com.google.common.base.Joiner; 23import com.google.common.collect.ImmutableList; 24import com.google.common.collect.ImmutableMap; 25import com.google.turbine.binder.bound.SourceTypeBoundClass; 26import com.google.turbine.binder.bound.TypeBoundClass; 27import com.google.turbine.binder.bound.TypeBoundClass.AnnoInfo; 28import com.google.turbine.binder.bound.TypeBoundClass.FieldInfo; 29import com.google.turbine.binder.bound.TypeBoundClass.MethodInfo; 30import com.google.turbine.binder.env.CompoundEnv; 31import com.google.turbine.binder.env.Env; 32import com.google.turbine.binder.lookup.LookupKey; 33import com.google.turbine.binder.lookup.LookupResult; 34import com.google.turbine.binder.sym.ClassSymbol; 35import com.google.turbine.binder.sym.FieldSymbol; 36import com.google.turbine.model.Const; 37import com.google.turbine.model.TurbineConstantTypeKind; 38import com.google.turbine.model.TurbineFlag; 39import com.google.turbine.tree.Tree; 40import com.google.turbine.tree.Tree.ArrayInit; 41import com.google.turbine.tree.Tree.Binary; 42import com.google.turbine.tree.Tree.ClassLiteral; 43import com.google.turbine.tree.Tree.ClassTy; 44import com.google.turbine.tree.Tree.Conditional; 45import com.google.turbine.tree.Tree.ConstVarName; 46import com.google.turbine.tree.Tree.Expression; 47import com.google.turbine.tree.Tree.PrimTy; 48import com.google.turbine.tree.Tree.TypeCast; 49import com.google.turbine.tree.Tree.Unary; 50import com.google.turbine.type.Type; 51import java.util.LinkedHashMap; 52import java.util.Map; 53 54/** Constant expression evaluation. */ 55public class ConstEvaluator { 56 57 /** The symbol of the enclosing class. */ 58 private final ClassSymbol sym; 59 60 /** The bound node of the enclosing class. */ 61 private final SourceTypeBoundClass owner; 62 63 /** The constant variable environment. */ 64 private final Env<FieldSymbol, Const.Value> values; 65 66 /** The class environment. */ 67 private final CompoundEnv<ClassSymbol, TypeBoundClass> env; 68 69 public ConstEvaluator( 70 ClassSymbol sym, 71 SourceTypeBoundClass owner, 72 Env<FieldSymbol, Const.Value> values, 73 CompoundEnv<ClassSymbol, TypeBoundClass> env) { 74 75 this.sym = sym; 76 this.owner = owner; 77 this.values = values; 78 this.env = env; 79 } 80 81 /** Evaluates the given expression's value. */ 82 public Const eval(Tree t) { 83 switch (t.kind()) { 84 case LITERAL: 85 { 86 Const.Value a = (Const.Value) ((Tree.Literal) t).value(); 87 if (a == null) { 88 return null; 89 } 90 switch (a.constantTypeKind()) { 91 case CHAR: 92 return new Const.CharValue(((com.google.turbine.model.Const.CharValue) a).value()); 93 case INT: 94 return new Const.IntValue(((com.google.turbine.model.Const.IntValue) a).value()); 95 case LONG: 96 return new Const.LongValue(((com.google.turbine.model.Const.LongValue) a).value()); 97 case FLOAT: 98 return new Const.FloatValue(((com.google.turbine.model.Const.FloatValue) a).value()); 99 case DOUBLE: 100 return new Const.DoubleValue( 101 ((com.google.turbine.model.Const.DoubleValue) a).value()); 102 case BOOLEAN: 103 return new Const.BooleanValue( 104 ((com.google.turbine.model.Const.BooleanValue) a).value()); 105 case STRING: 106 return new Const.StringValue( 107 ((com.google.turbine.model.Const.StringValue) a).value()); 108 case SHORT: 109 case BYTE: 110 case NULL: 111 default: 112 throw new AssertionError(a.constantTypeKind()); 113 } 114 } 115 case VOID_TY: 116 throw new AssertionError(t.kind()); 117 case CONST_VAR_NAME: 118 return evalConstVar((ConstVarName) t); 119 case CLASS_LITERAL: 120 return evalClassLiteral((ClassLiteral) t); 121 case BINARY: 122 return evalBinary((Binary) t); 123 case TYPE_CAST: 124 return evalCast((TypeCast) t); 125 case UNARY: 126 return evalUnary((Unary) t); 127 case CONDITIONAL: 128 return evalConditional((Conditional) t); 129 case ARRAY_INIT: 130 return evalArrayInit((ArrayInit) t); 131 case ANNO_EXPR: 132 return evalAnno(((Tree.AnnoExpr) t).value()); 133 default: 134 throw new AssertionError(t.kind()); 135 } 136 } 137 138 /** Evaluates a class literal. */ 139 // TODO(cushon): consider distinguishing between constant field and annotation values, 140 // and only allowing class literals / enum constants in the latter 141 Const evalClassLiteral(ClassLiteral t) { 142 switch (t.type().kind()) { 143 case PRIM_TY: 144 return new Const.ClassValue(new Type.PrimTy(((PrimTy) t.type()).tykind())); 145 case VOID_TY: 146 return new Const.ClassValue(Type.VOID); 147 case CLASS_TY: 148 { 149 ClassTy classTy = (ClassTy) t.type(); 150 ClassSymbol classSym = HierarchyBinder.resolveClass(env, owner.scope(), sym, classTy); 151 return new Const.ClassValue(Type.ClassTy.asNonParametricClassTy(classSym)); 152 } 153 default: 154 throw new AssertionError(t.type().kind()); 155 } 156 } 157 158 /** Evaluates a reference to another constant variable. */ 159 Const evalConstVar(ConstVarName t) { 160 LookupResult result = owner.scope().lookup(new LookupKey(t.name())); 161 if (result != null) { 162 return resolve(result); 163 } 164 String simple = t.name().get(0); 165 FieldInfo info = lexicalField(env, sym, simple); 166 if (info != null) { 167 return values.get(info.sym()); 168 } 169 // This resolves the top-level class symbol, and then doesn inherited member 170 // lookup on the rest of the names. The spec only allows the final name to be 171 // inherited and requires canonical form for the rest, so consider enforcing 172 // that. 173 result = owner.memberImports().lookup(simple); 174 if (result != null) { 175 return resolve(result); 176 } 177 throw new AssertionError(Joiner.on('.').join(t.name())); 178 } 179 180 private Const resolve(LookupResult result) { 181 ClassSymbol sym = (ClassSymbol) result.sym(); 182 for (int i = 0; i < result.remaining().size() - 1; i++) { 183 sym = Resolve.resolve(env, sym, result.remaining().get(i)); 184 } 185 String name = result.remaining().get(result.remaining().size() - 1); 186 FieldInfo field = inheritedField(env, sym, name); 187 if ((field.access() & TurbineFlag.ACC_ENUM) == TurbineFlag.ACC_ENUM) { 188 return new Const.EnumConstantValue(field.sym()); 189 } 190 verifyNotNull(field, "%s", result); 191 return values.get(field.sym()); 192 } 193 194 /** Search for constant variables in lexically enclosing scopes. */ 195 private static FieldInfo lexicalField( 196 Env<ClassSymbol, TypeBoundClass> env, ClassSymbol sym, String name) { 197 while (sym != null) { 198 TypeBoundClass info = env.get(sym); 199 FieldInfo field = inheritedField(env, sym, name); 200 if (field != null) { 201 return field; 202 } 203 sym = info.owner(); 204 } 205 return null; 206 } 207 208 private static FieldInfo inheritedField( 209 Env<ClassSymbol, TypeBoundClass> env, ClassSymbol sym, String name) { 210 while (sym != null) { 211 TypeBoundClass info = env.get(sym); 212 FieldInfo field = getField(info, name); 213 if (field != null) { 214 return field; 215 } 216 sym = info.superclass(); 217 } 218 return null; 219 } 220 221 private static FieldInfo getField(TypeBoundClass info, String name) { 222 for (FieldInfo f : info.fields()) { 223 if (f.name().equals(name)) { 224 return f; 225 } 226 } 227 return null; 228 } 229 230 /** Casts the value to the given type. */ 231 static Const cast(Type ty, Const value) { 232 checkNotNull(value); 233 switch (ty.tyKind()) { 234 case CLASS_TY: 235 case TY_VAR: 236 return value; 237 case PRIM_TY: 238 return coerce((Const.Value) value, ((Type.PrimTy) ty).primkind()); 239 default: 240 throw new AssertionError(ty.tyKind()); 241 } 242 } 243 244 private static Const.Value coerce(Const.Value value, TurbineConstantTypeKind kind) { 245 switch (kind) { 246 case BOOLEAN: 247 return value.asBoolean(); 248 case STRING: 249 return value.asString(); 250 case LONG: 251 return value.asLong(); 252 case INT: 253 return value.asInteger(); 254 case BYTE: 255 return value.asByte(); 256 case CHAR: 257 return value.asChar(); 258 case SHORT: 259 return value.asShort(); 260 case DOUBLE: 261 return value.asDouble(); 262 case FLOAT: 263 return value.asFloat(); 264 default: 265 throw new AssertionError(kind); 266 } 267 } 268 269 private Const.Value evalValue(Expression tree) { 270 return (Const.Value) eval(tree); 271 } 272 273 private Const.Value evalConditional(Conditional t) { 274 return evalValue(t.cond()).asBoolean().value() ? evalValue(t.iftrue()) : evalValue(t.iffalse()); 275 } 276 277 private Const.Value evalUnary(Unary t) { 278 Const.Value expr = evalValue(t.expr()); 279 switch (t.op()) { 280 case NOT: 281 switch (expr.constantTypeKind()) { 282 case BOOLEAN: 283 return new Const.BooleanValue(!expr.asBoolean().value()); 284 default: 285 throw new AssertionError(expr.constantTypeKind()); 286 } 287 case BITWISE_COMP: 288 switch (expr.constantTypeKind()) { 289 case INT: 290 return new Const.IntValue(~expr.asInteger().value()); 291 case LONG: 292 return new Const.LongValue(~expr.asLong().value()); 293 case BYTE: 294 return new Const.ByteValue((byte) ~expr.asByte().value()); 295 case SHORT: 296 return new Const.ShortValue((short) ~expr.asShort().value()); 297 case CHAR: 298 return new Const.CharValue((char) ~expr.asChar().value()); 299 default: 300 throw new AssertionError(expr.constantTypeKind()); 301 } 302 case UNARY_PLUS: 303 switch (expr.constantTypeKind()) { 304 case INT: 305 return new Const.IntValue(+expr.asInteger().value()); 306 case LONG: 307 return new Const.LongValue(+expr.asLong().value()); 308 case BYTE: 309 return new Const.ByteValue((byte) +expr.asByte().value()); 310 case SHORT: 311 return new Const.ShortValue((short) +expr.asShort().value()); 312 case CHAR: 313 return new Const.CharValue((char) +expr.asChar().value()); 314 case FLOAT: 315 return new Const.FloatValue(+expr.asFloat().value()); 316 case DOUBLE: 317 return new Const.DoubleValue(+expr.asDouble().value()); 318 default: 319 throw new AssertionError(expr.constantTypeKind()); 320 } 321 case NEG: 322 switch (expr.constantTypeKind()) { 323 case INT: 324 return new Const.IntValue(-expr.asInteger().value()); 325 case BYTE: 326 return new Const.ByteValue((byte) -expr.asByte().value()); 327 case SHORT: 328 return new Const.ShortValue((short) -expr.asShort().value()); 329 case CHAR: 330 return new Const.CharValue((char) -expr.asChar().value()); 331 case LONG: 332 return new Const.LongValue(-expr.asLong().value()); 333 case FLOAT: 334 return new Const.FloatValue(-expr.asFloat().value()); 335 case DOUBLE: 336 return new Const.DoubleValue(-expr.asDouble().value()); 337 default: 338 throw new AssertionError(expr.constantTypeKind()); 339 } 340 default: 341 throw new AssertionError(t.op()); 342 } 343 } 344 345 private Const.Value evalCast(TypeCast t) { 346 Const.Value expr = evalValue(t.expr()); 347 switch (t.ty().kind()) { 348 case PRIM_TY: 349 return coerce(expr, ((Tree.PrimTy) t.ty()).tykind()); 350 case CLASS_TY: 351 { 352 ClassTy classTy = (ClassTy) t.ty(); 353 // TODO(cushon): check package? 354 if (!classTy.name().equals("String")) { 355 throw new AssertionError(classTy); 356 } 357 return expr.asString(); 358 } 359 default: 360 throw new AssertionError(t.ty().kind()); 361 } 362 } 363 364 static Const.Value add(Const.Value a, Const.Value b) { 365 if (a.constantTypeKind() == TurbineConstantTypeKind.STRING 366 || b.constantTypeKind() == TurbineConstantTypeKind.STRING) { 367 return new Const.StringValue(a.asString().value() + b.asString().value()); 368 } 369 TurbineConstantTypeKind type = promoteBinary(a, b); 370 a = coerce(a, type); 371 b = coerce(b, type); 372 switch (type) { 373 case INT: 374 return new Const.IntValue(a.asInteger().value() + b.asInteger().value()); 375 case LONG: 376 return new Const.LongValue(a.asLong().value() + b.asLong().value()); 377 case FLOAT: 378 return new Const.FloatValue(a.asFloat().value() + b.asFloat().value()); 379 case DOUBLE: 380 return new Const.DoubleValue(a.asDouble().value() + b.asDouble().value()); 381 default: 382 throw new AssertionError(type); 383 } 384 } 385 386 static Const.Value subtract(Const.Value a, Const.Value b) { 387 TurbineConstantTypeKind type = promoteBinary(a, b); 388 a = coerce(a, type); 389 b = coerce(b, type); 390 switch (type) { 391 case INT: 392 return new Const.IntValue(a.asInteger().value() - b.asInteger().value()); 393 case LONG: 394 return new Const.LongValue(a.asLong().value() - b.asLong().value()); 395 case FLOAT: 396 return new Const.FloatValue(a.asFloat().value() - b.asFloat().value()); 397 case DOUBLE: 398 return new Const.DoubleValue(a.asDouble().value() - b.asDouble().value()); 399 default: 400 throw new AssertionError(type); 401 } 402 } 403 404 static Const.Value mult(Const.Value a, Const.Value b) { 405 TurbineConstantTypeKind type = promoteBinary(a, b); 406 a = coerce(a, type); 407 b = coerce(b, type); 408 switch (type) { 409 case INT: 410 return new Const.IntValue(a.asInteger().value() * b.asInteger().value()); 411 case LONG: 412 return new Const.LongValue(a.asLong().value() * b.asLong().value()); 413 case FLOAT: 414 return new Const.FloatValue(a.asFloat().value() * b.asFloat().value()); 415 case DOUBLE: 416 return new Const.DoubleValue(a.asDouble().value() * b.asDouble().value()); 417 default: 418 throw new AssertionError(type); 419 } 420 } 421 422 static Const.Value divide(Const.Value a, Const.Value b) { 423 TurbineConstantTypeKind type = promoteBinary(a, b); 424 a = coerce(a, type); 425 b = coerce(b, type); 426 switch (type) { 427 case INT: 428 return new Const.IntValue(a.asInteger().value() / b.asInteger().value()); 429 case LONG: 430 return new Const.LongValue(a.asLong().value() / b.asLong().value()); 431 case FLOAT: 432 return new Const.FloatValue(a.asFloat().value() / b.asFloat().value()); 433 case DOUBLE: 434 return new Const.DoubleValue(a.asDouble().value() / b.asDouble().value()); 435 default: 436 throw new AssertionError(type); 437 } 438 } 439 440 static Const.Value mod(Const.Value a, Const.Value b) { 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 final int INT_SHIFT_MASK = 0b11111; 459 460 static final int LONG_SHIFT_MASK = 0b111111; 461 462 static Const.Value shiftLeft(Const.Value a, Const.Value b) { 463 a = promoteUnary(a); 464 b = promoteUnary(b); 465 switch (a.constantTypeKind()) { 466 case INT: 467 return new Const.IntValue( 468 a.asInteger().value() << (b.asInteger().value() & INT_SHIFT_MASK)); 469 case LONG: 470 return new Const.LongValue(a.asLong().value() << (b.asInteger().value() & LONG_SHIFT_MASK)); 471 default: 472 throw new AssertionError(a.constantTypeKind()); 473 } 474 } 475 476 static Const.Value shiftRight(Const.Value a, Const.Value b) { 477 a = promoteUnary(a); 478 b = promoteUnary(b); 479 switch (a.constantTypeKind()) { 480 case INT: 481 return new Const.IntValue( 482 a.asInteger().value() >> (b.asInteger().value() & INT_SHIFT_MASK)); 483 case LONG: 484 return new Const.LongValue(a.asLong().value() >> (b.asInteger().value() & LONG_SHIFT_MASK)); 485 default: 486 throw new AssertionError(a.constantTypeKind()); 487 } 488 } 489 490 static Const.Value unsignedShiftRight(Const.Value a, Const.Value b) { 491 a = promoteUnary(a); 492 b = promoteUnary(b); 493 switch (a.constantTypeKind()) { 494 case INT: 495 return new Const.IntValue( 496 a.asInteger().value() >>> (b.asInteger().value() & INT_SHIFT_MASK)); 497 case LONG: 498 return new Const.LongValue( 499 a.asLong().value() >>> (b.asInteger().value() & LONG_SHIFT_MASK)); 500 default: 501 throw new AssertionError(a.constantTypeKind()); 502 } 503 } 504 505 static Const.Value lessThan(Const.Value a, Const.Value b) { 506 TurbineConstantTypeKind type = promoteBinary(a, b); 507 a = coerce(a, type); 508 b = coerce(b, type); 509 switch (type) { 510 case INT: 511 return new Const.BooleanValue(a.asInteger().value() < b.asInteger().value()); 512 case LONG: 513 return new Const.BooleanValue(a.asLong().value() < b.asLong().value()); 514 case FLOAT: 515 return new Const.BooleanValue(a.asFloat().value() < b.asFloat().value()); 516 case DOUBLE: 517 return new Const.BooleanValue(a.asDouble().value() < b.asDouble().value()); 518 default: 519 throw new AssertionError(type); 520 } 521 } 522 523 static Const.Value lessThanEqual(Const.Value a, Const.Value b) { 524 TurbineConstantTypeKind type = promoteBinary(a, b); 525 a = coerce(a, type); 526 b = coerce(b, type); 527 switch (type) { 528 case INT: 529 return new Const.BooleanValue(a.asInteger().value() <= b.asInteger().value()); 530 case LONG: 531 return new Const.BooleanValue(a.asLong().value() <= b.asLong().value()); 532 case FLOAT: 533 return new Const.BooleanValue(a.asFloat().value() <= b.asFloat().value()); 534 case DOUBLE: 535 return new Const.BooleanValue(a.asDouble().value() <= b.asDouble().value()); 536 default: 537 throw new AssertionError(type); 538 } 539 } 540 541 static Const.Value greaterThan(Const.Value a, Const.Value b) { 542 TurbineConstantTypeKind type = promoteBinary(a, b); 543 a = coerce(a, type); 544 b = coerce(b, type); 545 switch (type) { 546 case INT: 547 return new Const.BooleanValue(a.asInteger().value() > b.asInteger().value()); 548 case LONG: 549 return new Const.BooleanValue(a.asLong().value() > b.asLong().value()); 550 case FLOAT: 551 return new Const.BooleanValue(a.asFloat().value() > b.asFloat().value()); 552 case DOUBLE: 553 return new Const.BooleanValue(a.asDouble().value() > b.asDouble().value()); 554 default: 555 throw new AssertionError(type); 556 } 557 } 558 559 static Const.Value greaterThanEqual(Const.Value a, Const.Value b) { 560 TurbineConstantTypeKind type = promoteBinary(a, b); 561 a = coerce(a, type); 562 b = coerce(b, type); 563 switch (type) { 564 case INT: 565 return new Const.BooleanValue(a.asInteger().value() >= b.asInteger().value()); 566 case LONG: 567 return new Const.BooleanValue(a.asLong().value() >= b.asLong().value()); 568 case FLOAT: 569 return new Const.BooleanValue(a.asFloat().value() >= b.asFloat().value()); 570 case DOUBLE: 571 return new Const.BooleanValue(a.asDouble().value() >= b.asDouble().value()); 572 default: 573 throw new AssertionError(type); 574 } 575 } 576 577 static Const.Value equal(Const.Value a, Const.Value b) { 578 switch (a.constantTypeKind()) { 579 case STRING: 580 return new Const.BooleanValue(a.asString().value().equals(b.asString().value())); 581 case BOOLEAN: 582 return new Const.BooleanValue(a.asBoolean().value() == b.asBoolean().value()); 583 default: 584 break; 585 } 586 TurbineConstantTypeKind type = promoteBinary(a, b); 587 a = coerce(a, type); 588 b = coerce(b, type); 589 switch (type) { 590 case INT: 591 return new Const.BooleanValue(a.asInteger().value() == b.asInteger().value()); 592 case LONG: 593 return new Const.BooleanValue(a.asLong().value() == b.asLong().value()); 594 case FLOAT: 595 return new Const.BooleanValue(a.asFloat().value() == b.asFloat().value()); 596 case DOUBLE: 597 return new Const.BooleanValue(a.asDouble().value() == b.asDouble().value()); 598 default: 599 throw new AssertionError(type); 600 } 601 } 602 603 static Const.Value notEqual(Const.Value a, Const.Value b) { 604 switch (a.constantTypeKind()) { 605 case STRING: 606 return new Const.BooleanValue(!a.asString().value().equals(b.asString().value())); 607 case BOOLEAN: 608 return new Const.BooleanValue(a.asBoolean().value() != b.asBoolean().value()); 609 default: 610 break; 611 } 612 TurbineConstantTypeKind type = promoteBinary(a, b); 613 a = coerce(a, type); 614 b = coerce(b, type); 615 switch (type) { 616 case INT: 617 return new Const.BooleanValue(a.asInteger().value() != b.asInteger().value()); 618 case LONG: 619 return new Const.BooleanValue(a.asLong().value() != b.asLong().value()); 620 case FLOAT: 621 return new Const.BooleanValue(a.asFloat().value() != b.asFloat().value()); 622 case DOUBLE: 623 return new Const.BooleanValue(a.asDouble().value() != b.asDouble().value()); 624 default: 625 throw new AssertionError(type); 626 } 627 } 628 629 static Const.Value bitwiseAnd(Const.Value a, Const.Value b) { 630 switch (a.constantTypeKind()) { 631 case BOOLEAN: 632 return new Const.BooleanValue(a.asBoolean().value() & b.asBoolean().value()); 633 default: 634 break; 635 } 636 TurbineConstantTypeKind type = promoteBinary(a, b); 637 a = coerce(a, type); 638 b = coerce(b, type); 639 switch (type) { 640 case INT: 641 return new Const.IntValue(a.asInteger().value() & b.asInteger().value()); 642 case LONG: 643 return new Const.LongValue(a.asLong().value() & b.asLong().value()); 644 default: 645 throw new AssertionError(type); 646 } 647 } 648 649 static Const.Value bitwiseOr(Const.Value a, Const.Value b) { 650 switch (a.constantTypeKind()) { 651 case BOOLEAN: 652 return new Const.BooleanValue(a.asBoolean().value() | b.asBoolean().value()); 653 default: 654 break; 655 } 656 TurbineConstantTypeKind type = promoteBinary(a, b); 657 a = coerce(a, type); 658 b = coerce(b, type); 659 switch (type) { 660 case INT: 661 return new Const.IntValue(a.asInteger().value() | b.asInteger().value()); 662 case LONG: 663 return new Const.LongValue(a.asLong().value() | b.asLong().value()); 664 default: 665 throw new AssertionError(type); 666 } 667 } 668 669 static Const.Value bitwiseXor(Const.Value a, Const.Value b) { 670 switch (a.constantTypeKind()) { 671 case BOOLEAN: 672 return new Const.BooleanValue(a.asBoolean().value() ^ b.asBoolean().value()); 673 default: 674 break; 675 } 676 TurbineConstantTypeKind type = promoteBinary(a, b); 677 a = coerce(a, type); 678 b = coerce(b, type); 679 switch (type) { 680 case INT: 681 return new Const.IntValue(a.asInteger().value() ^ b.asInteger().value()); 682 case LONG: 683 return new Const.LongValue(a.asLong().value() ^ b.asLong().value()); 684 default: 685 throw new AssertionError(type); 686 } 687 } 688 689 private Const.Value evalBinary(Binary t) { 690 Const.Value lhs = evalValue(t.lhs()); 691 Const.Value rhs = evalValue(t.rhs()); 692 switch (t.op()) { 693 case PLUS: 694 return add(lhs, rhs); 695 case MINUS: 696 return subtract(lhs, rhs); 697 case MULT: 698 return mult(lhs, rhs); 699 case DIVIDE: 700 return divide(lhs, rhs); 701 case MODULO: 702 return mod(lhs, rhs); 703 case SHIFT_LEFT: 704 return shiftLeft(lhs, rhs); 705 case SHIFT_RIGHT: 706 return shiftRight(lhs, rhs); 707 case UNSIGNED_SHIFT_RIGHT: 708 return unsignedShiftRight(lhs, rhs); 709 case LESS_THAN: 710 return lessThan(lhs, rhs); 711 case GREATER_THAN: 712 return greaterThan(lhs, rhs); 713 case LESS_THAN_EQ: 714 return lessThanEqual(lhs, rhs); 715 case GREATER_THAN_EQ: 716 return greaterThanEqual(lhs, rhs); 717 case EQUAL: 718 return equal(lhs, rhs); 719 case NOT_EQUAL: 720 return notEqual(lhs, rhs); 721 case AND: 722 return new Const.BooleanValue(lhs.asBoolean().value() && rhs.asBoolean().value()); 723 case OR: 724 return new Const.BooleanValue(lhs.asBoolean().value() || rhs.asBoolean().value()); 725 case BITWISE_AND: 726 return bitwiseAnd(lhs, rhs); 727 case BITWISE_XOR: 728 return bitwiseXor(lhs, rhs); 729 case BITWISE_OR: 730 return bitwiseOr(lhs, rhs); 731 default: 732 throw new AssertionError(t.op()); 733 } 734 } 735 736 private static Const.Value promoteUnary(Const.Value v) { 737 switch (v.constantTypeKind()) { 738 case CHAR: 739 case SHORT: 740 case BYTE: 741 return v.asInteger(); 742 case INT: 743 case LONG: 744 case FLOAT: 745 case DOUBLE: 746 return v; 747 default: 748 throw new AssertionError(v.constantTypeKind()); 749 } 750 } 751 752 private static TurbineConstantTypeKind promoteBinary(Const.Value a, Const.Value b) { 753 a = promoteUnary(a); 754 b = promoteUnary(b); 755 switch (a.constantTypeKind()) { 756 case INT: 757 switch (b.constantTypeKind()) { 758 case INT: 759 case LONG: 760 case DOUBLE: 761 case FLOAT: 762 return b.constantTypeKind(); 763 default: 764 throw new AssertionError(b.constantTypeKind()); 765 } 766 case LONG: 767 switch (b.constantTypeKind()) { 768 case INT: 769 return TurbineConstantTypeKind.LONG; 770 case LONG: 771 case DOUBLE: 772 case FLOAT: 773 return b.constantTypeKind(); 774 default: 775 throw new AssertionError(b.constantTypeKind()); 776 } 777 case FLOAT: 778 switch (b.constantTypeKind()) { 779 case INT: 780 case LONG: 781 case FLOAT: 782 return TurbineConstantTypeKind.FLOAT; 783 case DOUBLE: 784 return TurbineConstantTypeKind.DOUBLE; 785 default: 786 throw new AssertionError(b.constantTypeKind()); 787 } 788 case DOUBLE: 789 switch (b.constantTypeKind()) { 790 case INT: 791 case LONG: 792 case FLOAT: 793 case DOUBLE: 794 return TurbineConstantTypeKind.DOUBLE; 795 default: 796 throw new AssertionError(b.constantTypeKind()); 797 } 798 default: 799 throw new AssertionError(a.constantTypeKind()); 800 } 801 } 802 803 /** 804 * Evaluates annotation arguments given the symbol of the annotation declaration and a list of 805 * expression trees. 806 */ 807 AnnoInfo evaluateAnnotation(ClassSymbol sym, ImmutableList<Expression> args) { 808 Map<String, Type> template = new LinkedHashMap<>(); 809 for (MethodInfo method : env.get(sym).methods()) { 810 template.put(method.name(), method.returnType()); 811 } 812 813 ImmutableMap.Builder<String, Const> values = ImmutableMap.builder(); 814 for (Expression arg : args) { 815 Expression expr; 816 String key; 817 if (arg.kind() == Tree.Kind.ASSIGN) { 818 Tree.Assign assign = (Tree.Assign) arg; 819 key = assign.name(); 820 expr = assign.expr(); 821 } else { 822 // expand the implicit 'value' name; `@Foo(42)` is sugar for `@Foo(value=42)` 823 key = "value"; 824 expr = arg; 825 } 826 Type ty = template.get(key); 827 Const value = evalAnnotationValue(expr, ty); 828 values.put(key, value); 829 } 830 return new AnnoInfo(sym, args, values.build()); 831 } 832 833 private Const.AnnotationValue evalAnno(Tree.Anno t) { 834 LookupResult result = owner.scope().lookup(new LookupKey(t.name())); 835 ClassSymbol sym = (ClassSymbol) result.sym(); 836 for (String name : result.remaining()) { 837 sym = Resolve.resolve(env, sym, name); 838 } 839 AnnoInfo annoInfo = evaluateAnnotation(sym, t.args()); 840 return new Const.AnnotationValue(annoInfo.sym(), annoInfo.values()); 841 } 842 843 private Const.ArrayInitValue evalArrayInit(ArrayInit t) { 844 ImmutableList.Builder<Const> elements = ImmutableList.builder(); 845 for (Expression e : t.exprs()) { 846 elements.add(eval(e)); 847 } 848 return new Const.ArrayInitValue(elements.build()); 849 } 850 851 Const evalAnnotationValue(Tree tree, Type ty) { 852 Const value = eval(tree); 853 switch (ty.tyKind()) { 854 case PRIM_TY: 855 return coerce((Const.Value) value, ((Type.PrimTy) ty).primkind()); 856 case CLASS_TY: 857 case TY_VAR: 858 return value; 859 case ARRAY_TY: 860 { 861 if (value.kind() == Const.Kind.ARRAY) { 862 return value; 863 } 864 Type.ArrayTy aty = (Type.ArrayTy) ty; 865 return new Const.ArrayInitValue(ImmutableList.of(cast(aty.elementType(), value))); 866 } 867 default: 868 throw new AssertionError(ty.tyKind()); 869 } 870 } 871} 872