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