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