1bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon/*
2bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon * Copyright 2016 Google Inc. All Rights Reserved.
3bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon *
4bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon * Licensed under the Apache License, Version 2.0 (the "License");
5bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon * you may not use this file except in compliance with the License.
6bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon * You may obtain a copy of the License at
7bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon *
8bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon *     http://www.apache.org/licenses/LICENSE-2.0
9bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon *
10bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon * Unless required by applicable law or agreed to in writing, software
11bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon * distributed under the License is distributed on an "AS IS" BASIS,
12bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon * See the License for the specific language governing permissions and
14bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon * limitations under the License.
15bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon */
16bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon
17bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushonpackage com.google.turbine.binder;
18bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon
19e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushonimport static com.google.common.base.Preconditions.checkNotNull;
20bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon
214d51bb2c21dffcb267e9b3a3538117adc6009e57cushonimport com.google.common.collect.ImmutableList;
224d51bb2c21dffcb267e9b3a3538117adc6009e57cushonimport com.google.common.collect.ImmutableMap;
235a010f8e1f9613af8a23aaab28a64d6c83eb48fbcushonimport com.google.common.collect.Iterables;
2405878b6cb86f32245891d6e4504a8b1e7fcd2155cushonimport com.google.turbine.binder.bound.AnnotationValue;
2505878b6cb86f32245891d6e4504a8b1e7fcd2155cushonimport com.google.turbine.binder.bound.ClassValue;
2605878b6cb86f32245891d6e4504a8b1e7fcd2155cushonimport com.google.turbine.binder.bound.EnumConstantValue;
27bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushonimport com.google.turbine.binder.bound.SourceTypeBoundClass;
28bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushonimport com.google.turbine.binder.bound.TypeBoundClass;
29bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushonimport com.google.turbine.binder.bound.TypeBoundClass.FieldInfo;
304d51bb2c21dffcb267e9b3a3538117adc6009e57cushonimport com.google.turbine.binder.bound.TypeBoundClass.MethodInfo;
31bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushonimport com.google.turbine.binder.env.CompoundEnv;
32bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushonimport com.google.turbine.binder.env.Env;
3316d4fb60dd03fe84f50a96d42db6180a286fc3dbcushonimport com.google.turbine.binder.lookup.CompoundScope;
34bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushonimport com.google.turbine.binder.lookup.LookupKey;
35bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushonimport com.google.turbine.binder.lookup.LookupResult;
36bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushonimport com.google.turbine.binder.sym.ClassSymbol;
37bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushonimport com.google.turbine.binder.sym.FieldSymbol;
38b0445ae9c37a1fab07fb5f234653e8ea072bf9fccushonimport com.google.turbine.diag.TurbineError;
39b25a536a58cfc542d70a118aebc30d3a9dea5654cushonimport com.google.turbine.diag.TurbineError.ErrorKind;
40bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushonimport com.google.turbine.model.Const;
41aa81f608f1790015683a9368bc15924fc9c89767cushonimport com.google.turbine.model.Const.Value;
42e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushonimport com.google.turbine.model.TurbineConstantTypeKind;
43bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushonimport com.google.turbine.model.TurbineFlag;
44bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushonimport com.google.turbine.tree.Tree;
453088f83b806b82d866d119e344da274105f42821cushonimport com.google.turbine.tree.Tree.ArrayInit;
46e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushonimport com.google.turbine.tree.Tree.Binary;
47c38ee7ae0239899e7f9d0d5243d8bed77836891ccushonimport com.google.turbine.tree.Tree.ClassLiteral;
48e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushonimport com.google.turbine.tree.Tree.ClassTy;
49e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushonimport com.google.turbine.tree.Tree.Conditional;
50bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushonimport com.google.turbine.tree.Tree.ConstVarName;
51e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushonimport com.google.turbine.tree.Tree.Expression;
52c38ee7ae0239899e7f9d0d5243d8bed77836891ccushonimport com.google.turbine.tree.Tree.PrimTy;
53e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushonimport com.google.turbine.tree.Tree.TypeCast;
54e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushonimport com.google.turbine.tree.Tree.Unary;
5505878b6cb86f32245891d6e4504a8b1e7fcd2155cushonimport com.google.turbine.type.AnnoInfo;
56bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushonimport com.google.turbine.type.Type;
5716d4fb60dd03fe84f50a96d42db6180a286fc3dbcushonimport java.util.ArrayDeque;
585a010f8e1f9613af8a23aaab28a64d6c83eb48fbcushonimport java.util.Iterator;
594d51bb2c21dffcb267e9b3a3538117adc6009e57cushonimport java.util.LinkedHashMap;
604d51bb2c21dffcb267e9b3a3538117adc6009e57cushonimport java.util.Map;
61bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon
625f9257de4904d710941a3f434de0e0c3618a4e75cushon/**
635f9257de4904d710941a3f434de0e0c3618a4e75cushon * Constant expression evaluation.
645f9257de4904d710941a3f434de0e0c3618a4e75cushon *
655f9257de4904d710941a3f434de0e0c3618a4e75cushon * <p>JLS §15.4 requires this class to be strictfp.
665f9257de4904d710941a3f434de0e0c3618a4e75cushon */
675f9257de4904d710941a3f434de0e0c3618a4e75cushonpublic strictfp class ConstEvaluator {
68bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon
693de8ed9a49a939e11961146bf5b6a41c20dc7f79cushon  /** The symbol of the originating class, for visibility checks. */
703de8ed9a49a939e11961146bf5b6a41c20dc7f79cushon  private final ClassSymbol origin;
713de8ed9a49a939e11961146bf5b6a41c20dc7f79cushon
723de8ed9a49a939e11961146bf5b6a41c20dc7f79cushon  /** The symbol of the enclosing class, for lexical field lookups. */
73c4fcb03ad72af457d0448f4207085c2a60b4ae52cushon  private final ClassSymbol owner;
74bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon
75bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon  /** The bound node of the enclosing class. */
76c4fcb03ad72af457d0448f4207085c2a60b4ae52cushon  private final SourceTypeBoundClass base;
77bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon
78bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon  /** The constant variable environment. */
79bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon  private final Env<FieldSymbol, Const.Value> values;
80bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon
81bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon  /** The class environment. */
82bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon  private final CompoundEnv<ClassSymbol, TypeBoundClass> env;
83bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon
8416d4fb60dd03fe84f50a96d42db6180a286fc3dbcushon  private final CompoundScope scope;
8516d4fb60dd03fe84f50a96d42db6180a286fc3dbcushon
86bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon  public ConstEvaluator(
873de8ed9a49a939e11961146bf5b6a41c20dc7f79cushon      ClassSymbol origin,
88c4fcb03ad72af457d0448f4207085c2a60b4ae52cushon      ClassSymbol owner,
89c4fcb03ad72af457d0448f4207085c2a60b4ae52cushon      SourceTypeBoundClass base,
9016d4fb60dd03fe84f50a96d42db6180a286fc3dbcushon      CompoundScope scope,
91bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon      Env<FieldSymbol, Const.Value> values,
92bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon      CompoundEnv<ClassSymbol, TypeBoundClass> env) {
93bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon
943de8ed9a49a939e11961146bf5b6a41c20dc7f79cushon    this.origin = origin;
95bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon    this.owner = owner;
96c4fcb03ad72af457d0448f4207085c2a60b4ae52cushon    this.base = base;
97bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon    this.values = values;
98bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon    this.env = env;
9916d4fb60dd03fe84f50a96d42db6180a286fc3dbcushon    this.scope = scope;
100bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon  }
101bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon
102bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon  /** Evaluates the given expression's value. */
1033088f83b806b82d866d119e344da274105f42821cushon  public Const eval(Tree t) {
104bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon    switch (t.kind()) {
105bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon      case LITERAL:
106bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon        {
107bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon          Const.Value a = (Const.Value) ((Tree.Literal) t).value();
108bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon          if (a == null) {
109bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon            return null;
110bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon          }
111bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon          switch (a.constantTypeKind()) {
112bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon            case CHAR:
113bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon              return new Const.CharValue(((com.google.turbine.model.Const.CharValue) a).value());
114bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon            case INT:
115bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon              return new Const.IntValue(((com.google.turbine.model.Const.IntValue) a).value());
116bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon            case LONG:
117bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon              return new Const.LongValue(((com.google.turbine.model.Const.LongValue) a).value());
118bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon            case FLOAT:
119bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon              return new Const.FloatValue(((com.google.turbine.model.Const.FloatValue) a).value());
120bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon            case DOUBLE:
121bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon              return new Const.DoubleValue(
122bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon                  ((com.google.turbine.model.Const.DoubleValue) a).value());
123bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon            case BOOLEAN:
124bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon              return new Const.BooleanValue(
125bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon                  ((com.google.turbine.model.Const.BooleanValue) a).value());
126bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon            case STRING:
127bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon              return new Const.StringValue(
128bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon                  ((com.google.turbine.model.Const.StringValue) a).value());
129bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon            case SHORT:
130bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon            case BYTE:
131bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon            case NULL:
132bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon            default:
133bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon              throw new AssertionError(a.constantTypeKind());
134bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon          }
135bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon        }
136bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon      case VOID_TY:
137bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon        throw new AssertionError(t.kind());
138bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon      case CONST_VAR_NAME:
139bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon        return evalConstVar((ConstVarName) t);
140c38ee7ae0239899e7f9d0d5243d8bed77836891ccushon      case CLASS_LITERAL:
141c38ee7ae0239899e7f9d0d5243d8bed77836891ccushon        return evalClassLiteral((ClassLiteral) t);
142bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon      case BINARY:
143e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return evalBinary((Binary) t);
144bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon      case TYPE_CAST:
145e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return evalCast((TypeCast) t);
146bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon      case UNARY:
147e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return evalUnary((Unary) t);
148bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon      case CONDITIONAL:
149e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return evalConditional((Conditional) t);
150bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon      case ARRAY_INIT:
1513088f83b806b82d866d119e344da274105f42821cushon        return evalArrayInit((ArrayInit) t);
15283d53bb2e7f30a1c344f4aaa4320668f9dbc12f4cushon      case ANNO_EXPR:
15383d53bb2e7f30a1c344f4aaa4320668f9dbc12f4cushon        return evalAnno(((Tree.AnnoExpr) t).value());
154bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon      default:
155bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon        throw new AssertionError(t.kind());
156bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon    }
157bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon  }
158bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon
159c38ee7ae0239899e7f9d0d5243d8bed77836891ccushon  /** Evaluates a class literal. */
160c38ee7ae0239899e7f9d0d5243d8bed77836891ccushon  Const evalClassLiteral(ClassLiteral t) {
161c4b9629cb88f39fb5a648e2081f43afbb2685766cushon    return new ClassValue(evalClassLiteralType(t.type()));
162c4b9629cb88f39fb5a648e2081f43afbb2685766cushon  }
163c4b9629cb88f39fb5a648e2081f43afbb2685766cushon
164c4b9629cb88f39fb5a648e2081f43afbb2685766cushon  private Type evalClassLiteralType(Tree.Type type) {
165c4b9629cb88f39fb5a648e2081f43afbb2685766cushon    switch (type.kind()) {
166c38ee7ae0239899e7f9d0d5243d8bed77836891ccushon      case PRIM_TY:
167c4b9629cb88f39fb5a648e2081f43afbb2685766cushon        return new Type.PrimTy(((PrimTy) type).tykind(), ImmutableList.of());
168c38ee7ae0239899e7f9d0d5243d8bed77836891ccushon      case VOID_TY:
169c4b9629cb88f39fb5a648e2081f43afbb2685766cushon        return Type.VOID;
170c38ee7ae0239899e7f9d0d5243d8bed77836891ccushon      case CLASS_TY:
171c4b9629cb88f39fb5a648e2081f43afbb2685766cushon        return Type.ClassTy.asNonParametricClassTy(resolveClass((ClassTy) type));
172c4b9629cb88f39fb5a648e2081f43afbb2685766cushon      case ARR_TY:
173c4b9629cb88f39fb5a648e2081f43afbb2685766cushon        return new Type.ArrayTy(
174c4b9629cb88f39fb5a648e2081f43afbb2685766cushon            evalClassLiteralType(((Tree.ArrTy) type).elem()), ImmutableList.of());
175c38ee7ae0239899e7f9d0d5243d8bed77836891ccushon      default:
176c4b9629cb88f39fb5a648e2081f43afbb2685766cushon        throw new AssertionError(type.kind());
177c38ee7ae0239899e7f9d0d5243d8bed77836891ccushon    }
178c38ee7ae0239899e7f9d0d5243d8bed77836891ccushon  }
179c38ee7ae0239899e7f9d0d5243d8bed77836891ccushon
18016d4fb60dd03fe84f50a96d42db6180a286fc3dbcushon  /**
18116d4fb60dd03fe84f50a96d42db6180a286fc3dbcushon   * Resolves the {@link ClassSymbol} for the given {@link Tree.ClassTy}, with handling for
18216d4fb60dd03fe84f50a96d42db6180a286fc3dbcushon   * non-canonical qualified type names.
18316d4fb60dd03fe84f50a96d42db6180a286fc3dbcushon   *
18416d4fb60dd03fe84f50a96d42db6180a286fc3dbcushon   * <p>Similar to {@link HierarchyBinder#resolveClass}, except we can't unconditionally consider
18516d4fb60dd03fe84f50a96d42db6180a286fc3dbcushon   * members of the current class (e.g. when binding constants inside annotations on that class),
18616d4fb60dd03fe84f50a96d42db6180a286fc3dbcushon   * and when we do want to consider members we can rely on them being in the current scope (it
18716d4fb60dd03fe84f50a96d42db6180a286fc3dbcushon   * isn't completed during the hierarchy phase).
18816d4fb60dd03fe84f50a96d42db6180a286fc3dbcushon   */
18916d4fb60dd03fe84f50a96d42db6180a286fc3dbcushon  private ClassSymbol resolveClass(ClassTy classTy) {
19016d4fb60dd03fe84f50a96d42db6180a286fc3dbcushon    ArrayDeque<String> flat = new ArrayDeque<>();
19116d4fb60dd03fe84f50a96d42db6180a286fc3dbcushon    for (ClassTy curr = classTy; curr != null; curr = curr.base().orNull()) {
19216d4fb60dd03fe84f50a96d42db6180a286fc3dbcushon      flat.addFirst(curr.name());
19316d4fb60dd03fe84f50a96d42db6180a286fc3dbcushon    }
19416d4fb60dd03fe84f50a96d42db6180a286fc3dbcushon    LookupResult result = scope.lookup(new LookupKey(flat));
19516d4fb60dd03fe84f50a96d42db6180a286fc3dbcushon    if (result == null) {
196b25a536a58cfc542d70a118aebc30d3a9dea5654cushon      throw error(classTy.position(), ErrorKind.SYMBOL_NOT_FOUND, flat.peekFirst());
19716d4fb60dd03fe84f50a96d42db6180a286fc3dbcushon    }
19816d4fb60dd03fe84f50a96d42db6180a286fc3dbcushon    ClassSymbol classSym = (ClassSymbol) result.sym();
19916d4fb60dd03fe84f50a96d42db6180a286fc3dbcushon    for (String bit : result.remaining()) {
2003de8ed9a49a939e11961146bf5b6a41c20dc7f79cushon      classSym = Resolve.resolve(env, origin, classSym, bit);
20116d4fb60dd03fe84f50a96d42db6180a286fc3dbcushon      if (classSym == null) {
202b25a536a58cfc542d70a118aebc30d3a9dea5654cushon        throw error(classTy.position(), ErrorKind.SYMBOL_NOT_FOUND, bit);
20316d4fb60dd03fe84f50a96d42db6180a286fc3dbcushon      }
20416d4fb60dd03fe84f50a96d42db6180a286fc3dbcushon    }
20516d4fb60dd03fe84f50a96d42db6180a286fc3dbcushon    return classSym;
20616d4fb60dd03fe84f50a96d42db6180a286fc3dbcushon  }
20716d4fb60dd03fe84f50a96d42db6180a286fc3dbcushon
208c38ee7ae0239899e7f9d0d5243d8bed77836891ccushon  /** Evaluates a reference to another constant variable. */
209bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon  Const evalConstVar(ConstVarName t) {
2105a010f8e1f9613af8a23aaab28a64d6c83eb48fbcushon    FieldInfo field = resolveField(t);
211a086f7ddb24d35d1c45a3524520d8bffbf1f213bcushon    if (field == null) {
212a086f7ddb24d35d1c45a3524520d8bffbf1f213bcushon      return null;
213a086f7ddb24d35d1c45a3524520d8bffbf1f213bcushon    }
2145a010f8e1f9613af8a23aaab28a64d6c83eb48fbcushon    if ((field.access() & TurbineFlag.ACC_ENUM) == TurbineFlag.ACC_ENUM) {
21505878b6cb86f32245891d6e4504a8b1e7fcd2155cushon      return new EnumConstantValue(field.sym());
216bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon    }
21710cea422ebb6f3c02cc0e1a744bd3b1515e1891ecushon    if (field.value() != null) {
21810cea422ebb6f3c02cc0e1a744bd3b1515e1891ecushon      return field.value();
21910cea422ebb6f3c02cc0e1a744bd3b1515e1891ecushon    }
2205a010f8e1f9613af8a23aaab28a64d6c83eb48fbcushon    return values.get(field.sym());
2215a010f8e1f9613af8a23aaab28a64d6c83eb48fbcushon  }
2225a010f8e1f9613af8a23aaab28a64d6c83eb48fbcushon
2235a010f8e1f9613af8a23aaab28a64d6c83eb48fbcushon  FieldInfo resolveField(ConstVarName t) {
2245a010f8e1f9613af8a23aaab28a64d6c83eb48fbcushon    String simpleName = t.name().get(0);
225c4fcb03ad72af457d0448f4207085c2a60b4ae52cushon    FieldInfo field = lexicalField(env, owner, simpleName);
2265a010f8e1f9613af8a23aaab28a64d6c83eb48fbcushon    if (field != null) {
2275a010f8e1f9613af8a23aaab28a64d6c83eb48fbcushon      return field;
228bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon    }
229125eca769fc3038f6466b6f1139b56945bf86ca9cushon    field = resolveQualifiedField(t);
230125eca769fc3038f6466b6f1139b56945bf86ca9cushon    if (field != null) {
231125eca769fc3038f6466b6f1139b56945bf86ca9cushon      return field;
232bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon    }
233c4fcb03ad72af457d0448f4207085c2a60b4ae52cushon    ClassSymbol classSymbol = base.memberImports().singleMemberImport(simpleName);
23475946a85fe655bafc006b96e4ddf01990d5f2f7ccushon    if (classSymbol != null) {
2353de8ed9a49a939e11961146bf5b6a41c20dc7f79cushon      field = Resolve.resolveField(env, origin, classSymbol, simpleName);
23675946a85fe655bafc006b96e4ddf01990d5f2f7ccushon      if (field != null) {
23775946a85fe655bafc006b96e4ddf01990d5f2f7ccushon        return field;
23875946a85fe655bafc006b96e4ddf01990d5f2f7ccushon      }
239bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon    }
240c4fcb03ad72af457d0448f4207085c2a60b4ae52cushon    Iterator<ClassSymbol> it = base.memberImports().onDemandImports();
2415a010f8e1f9613af8a23aaab28a64d6c83eb48fbcushon    while (it.hasNext()) {
2423de8ed9a49a939e11961146bf5b6a41c20dc7f79cushon      field = Resolve.resolveField(env, origin, it.next(), simpleName);
2432f66fb86c5de3e13b58b1a521ffc307c8cef1f50cushon      if (field == null) {
2442f66fb86c5de3e13b58b1a521ffc307c8cef1f50cushon        continue;
2455a010f8e1f9613af8a23aaab28a64d6c83eb48fbcushon      }
2462f66fb86c5de3e13b58b1a521ffc307c8cef1f50cushon      // resolve handles visibility of inherited members; on-demand imports of private members are
2472f66fb86c5de3e13b58b1a521ffc307c8cef1f50cushon      // a special case
2482f66fb86c5de3e13b58b1a521ffc307c8cef1f50cushon      if ((field.access() & TurbineFlag.ACC_PRIVATE) == TurbineFlag.ACC_PRIVATE) {
2492f66fb86c5de3e13b58b1a521ffc307c8cef1f50cushon        continue;
2502f66fb86c5de3e13b58b1a521ffc307c8cef1f50cushon      }
2512f66fb86c5de3e13b58b1a521ffc307c8cef1f50cushon      return field;
252bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon    }
2535a010f8e1f9613af8a23aaab28a64d6c83eb48fbcushon    return null;
254bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon  }
255bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon
256125eca769fc3038f6466b6f1139b56945bf86ca9cushon  private FieldInfo resolveQualifiedField(ConstVarName t) {
257125eca769fc3038f6466b6f1139b56945bf86ca9cushon    if (t.name().size() <= 1) {
258125eca769fc3038f6466b6f1139b56945bf86ca9cushon      return null;
259125eca769fc3038f6466b6f1139b56945bf86ca9cushon    }
260125eca769fc3038f6466b6f1139b56945bf86ca9cushon    LookupResult result = scope.lookup(new LookupKey(t.name()));
261125eca769fc3038f6466b6f1139b56945bf86ca9cushon    if (result == null) {
262125eca769fc3038f6466b6f1139b56945bf86ca9cushon      return null;
263125eca769fc3038f6466b6f1139b56945bf86ca9cushon    }
264125eca769fc3038f6466b6f1139b56945bf86ca9cushon    ClassSymbol sym = (ClassSymbol) result.sym();
265125eca769fc3038f6466b6f1139b56945bf86ca9cushon    for (int i = 0; i < result.remaining().size() - 1; i++) {
266125eca769fc3038f6466b6f1139b56945bf86ca9cushon      sym = Resolve.resolve(env, sym, sym, result.remaining().get(i));
267125eca769fc3038f6466b6f1139b56945bf86ca9cushon      if (sym == null) {
268125eca769fc3038f6466b6f1139b56945bf86ca9cushon        return null;
269125eca769fc3038f6466b6f1139b56945bf86ca9cushon      }
270125eca769fc3038f6466b6f1139b56945bf86ca9cushon    }
2713de8ed9a49a939e11961146bf5b6a41c20dc7f79cushon    return Resolve.resolveField(env, origin, sym, Iterables.getLast(result.remaining()));
272125eca769fc3038f6466b6f1139b56945bf86ca9cushon  }
273125eca769fc3038f6466b6f1139b56945bf86ca9cushon
274bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon  /** Search for constant variables in lexically enclosing scopes. */
275c4fcb03ad72af457d0448f4207085c2a60b4ae52cushon  private FieldInfo lexicalField(
276bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon      Env<ClassSymbol, TypeBoundClass> env, ClassSymbol sym, String name) {
277bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon    while (sym != null) {
278bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon      TypeBoundClass info = env.get(sym);
2793de8ed9a49a939e11961146bf5b6a41c20dc7f79cushon      FieldInfo field = Resolve.resolveField(env, origin, sym, name);
280bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon      if (field != null) {
281bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon        return field;
282bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon      }
283bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon      sym = info.owner();
284bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon    }
285bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon    return null;
286bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon  }
287bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon
288bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon  /** Casts the value to the given type. */
289e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  static Const cast(Type ty, Const value) {
290e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    checkNotNull(value);
291e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    switch (ty.tyKind()) {
292e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case CLASS_TY:
293e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case TY_VAR:
294e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return value;
295e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case PRIM_TY:
296e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return coerce((Const.Value) value, ((Type.PrimTy) ty).primkind());
297e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      default:
298e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        throw new AssertionError(ty.tyKind());
299e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    }
300e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  }
301e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon
302e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  private static Const.Value coerce(Const.Value value, TurbineConstantTypeKind kind) {
303e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    switch (kind) {
304e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case BOOLEAN:
305e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return value.asBoolean();
306e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case STRING:
307e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return value.asString();
308e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case LONG:
309e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return value.asLong();
310e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case INT:
311e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return value.asInteger();
312e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case BYTE:
313e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return value.asByte();
314e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case CHAR:
315e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return value.asChar();
316e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case SHORT:
317e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return value.asShort();
318e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case DOUBLE:
319e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return value.asDouble();
320e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case FLOAT:
321e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return value.asFloat();
322e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      default:
323e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        throw new AssertionError(kind);
324e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    }
325e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  }
326e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon
327e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  private Const.Value evalValue(Expression tree) {
328b622e5e85b83090ebec0aa9601c1348e91d20095cushon    Const result = eval(tree);
329b622e5e85b83090ebec0aa9601c1348e91d20095cushon    // TODO(cushon): consider distinguishing between constant field and annotation values,
330b622e5e85b83090ebec0aa9601c1348e91d20095cushon    // and only allowing class literals / enum constants in the latter
331b622e5e85b83090ebec0aa9601c1348e91d20095cushon    return (result instanceof Const.Value) ? (Const.Value) result : null;
332e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  }
333e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon
334e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  private Const.Value evalConditional(Conditional t) {
335806d6a5f4a319f2c00baf2334732024c5bdcacb5cushon    Const.Value condition = evalValue(t.cond());
336806d6a5f4a319f2c00baf2334732024c5bdcacb5cushon    if (condition == null) {
337806d6a5f4a319f2c00baf2334732024c5bdcacb5cushon      return null;
338806d6a5f4a319f2c00baf2334732024c5bdcacb5cushon    }
339806d6a5f4a319f2c00baf2334732024c5bdcacb5cushon    return condition.asBoolean().value() ? evalValue(t.iftrue()) : evalValue(t.iffalse());
340e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  }
341e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon
342e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  private Const.Value evalUnary(Unary t) {
343e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    Const.Value expr = evalValue(t.expr());
344806d6a5f4a319f2c00baf2334732024c5bdcacb5cushon    if (expr == null) {
345806d6a5f4a319f2c00baf2334732024c5bdcacb5cushon      return null;
346806d6a5f4a319f2c00baf2334732024c5bdcacb5cushon    }
347e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    switch (t.op()) {
348e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case NOT:
349aa81f608f1790015683a9368bc15924fc9c89767cushon        return unaryNegate(expr);
350e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case BITWISE_COMP:
351aa81f608f1790015683a9368bc15924fc9c89767cushon        return bitwiseComp(expr);
352e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case UNARY_PLUS:
353aa81f608f1790015683a9368bc15924fc9c89767cushon        return unaryPlus(expr);
354e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case NEG:
355aa81f608f1790015683a9368bc15924fc9c89767cushon        return unaryMinus(expr);
356e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      default:
357e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        throw new AssertionError(t.op());
358e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    }
359e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  }
360e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon
361aa81f608f1790015683a9368bc15924fc9c89767cushon  private Value unaryNegate(Value expr) {
362aa81f608f1790015683a9368bc15924fc9c89767cushon    switch (expr.constantTypeKind()) {
363aa81f608f1790015683a9368bc15924fc9c89767cushon      case BOOLEAN:
364aa81f608f1790015683a9368bc15924fc9c89767cushon        return new Const.BooleanValue(!expr.asBoolean().value());
365aa81f608f1790015683a9368bc15924fc9c89767cushon      default:
366aa81f608f1790015683a9368bc15924fc9c89767cushon        throw new AssertionError(expr.constantTypeKind());
367aa81f608f1790015683a9368bc15924fc9c89767cushon    }
368aa81f608f1790015683a9368bc15924fc9c89767cushon  }
369aa81f608f1790015683a9368bc15924fc9c89767cushon
370aa81f608f1790015683a9368bc15924fc9c89767cushon  private Value bitwiseComp(Value expr) {
371aa81f608f1790015683a9368bc15924fc9c89767cushon    expr = promoteUnary(expr);
372aa81f608f1790015683a9368bc15924fc9c89767cushon    switch (expr.constantTypeKind()) {
373aa81f608f1790015683a9368bc15924fc9c89767cushon      case INT:
374aa81f608f1790015683a9368bc15924fc9c89767cushon        return new Const.IntValue(~expr.asInteger().value());
375aa81f608f1790015683a9368bc15924fc9c89767cushon      case LONG:
376aa81f608f1790015683a9368bc15924fc9c89767cushon        return new Const.LongValue(~expr.asLong().value());
377aa81f608f1790015683a9368bc15924fc9c89767cushon      default:
378aa81f608f1790015683a9368bc15924fc9c89767cushon        throw new AssertionError(expr.constantTypeKind());
379aa81f608f1790015683a9368bc15924fc9c89767cushon    }
380aa81f608f1790015683a9368bc15924fc9c89767cushon  }
381aa81f608f1790015683a9368bc15924fc9c89767cushon
382aa81f608f1790015683a9368bc15924fc9c89767cushon  private Value unaryPlus(Value expr) {
383aa81f608f1790015683a9368bc15924fc9c89767cushon    expr = promoteUnary(expr);
384aa81f608f1790015683a9368bc15924fc9c89767cushon    switch (expr.constantTypeKind()) {
385aa81f608f1790015683a9368bc15924fc9c89767cushon      case INT:
386aa81f608f1790015683a9368bc15924fc9c89767cushon        return new Const.IntValue(+expr.asInteger().value());
387aa81f608f1790015683a9368bc15924fc9c89767cushon      case LONG:
388aa81f608f1790015683a9368bc15924fc9c89767cushon        return new Const.LongValue(+expr.asLong().value());
389aa81f608f1790015683a9368bc15924fc9c89767cushon      case FLOAT:
390aa81f608f1790015683a9368bc15924fc9c89767cushon        return new Const.FloatValue(+expr.asFloat().value());
391aa81f608f1790015683a9368bc15924fc9c89767cushon      case DOUBLE:
392aa81f608f1790015683a9368bc15924fc9c89767cushon        return new Const.DoubleValue(+expr.asDouble().value());
393aa81f608f1790015683a9368bc15924fc9c89767cushon      default:
394aa81f608f1790015683a9368bc15924fc9c89767cushon        throw new AssertionError(expr.constantTypeKind());
395aa81f608f1790015683a9368bc15924fc9c89767cushon    }
396aa81f608f1790015683a9368bc15924fc9c89767cushon  }
397aa81f608f1790015683a9368bc15924fc9c89767cushon
398aa81f608f1790015683a9368bc15924fc9c89767cushon  private Value unaryMinus(Value expr) {
399aa81f608f1790015683a9368bc15924fc9c89767cushon    expr = promoteUnary(expr);
400aa81f608f1790015683a9368bc15924fc9c89767cushon    switch (expr.constantTypeKind()) {
401aa81f608f1790015683a9368bc15924fc9c89767cushon      case INT:
402aa81f608f1790015683a9368bc15924fc9c89767cushon        return new Const.IntValue(-expr.asInteger().value());
403aa81f608f1790015683a9368bc15924fc9c89767cushon      case LONG:
404aa81f608f1790015683a9368bc15924fc9c89767cushon        return new Const.LongValue(-expr.asLong().value());
405aa81f608f1790015683a9368bc15924fc9c89767cushon      case FLOAT:
406aa81f608f1790015683a9368bc15924fc9c89767cushon        return new Const.FloatValue(-expr.asFloat().value());
407aa81f608f1790015683a9368bc15924fc9c89767cushon      case DOUBLE:
408aa81f608f1790015683a9368bc15924fc9c89767cushon        return new Const.DoubleValue(-expr.asDouble().value());
409aa81f608f1790015683a9368bc15924fc9c89767cushon      default:
410aa81f608f1790015683a9368bc15924fc9c89767cushon        throw new AssertionError(expr.constantTypeKind());
411aa81f608f1790015683a9368bc15924fc9c89767cushon    }
412aa81f608f1790015683a9368bc15924fc9c89767cushon  }
4133de8ed9a49a939e11961146bf5b6a41c20dc7f79cushon
414e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  private Const.Value evalCast(TypeCast t) {
415e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    Const.Value expr = evalValue(t.expr());
416806d6a5f4a319f2c00baf2334732024c5bdcacb5cushon    if (expr == null) {
417806d6a5f4a319f2c00baf2334732024c5bdcacb5cushon      return null;
418806d6a5f4a319f2c00baf2334732024c5bdcacb5cushon    }
419e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    switch (t.ty().kind()) {
420e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case PRIM_TY:
421e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return coerce(expr, ((Tree.PrimTy) t.ty()).tykind());
422e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case CLASS_TY:
423e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        {
424e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon          ClassTy classTy = (ClassTy) t.ty();
425e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon          // TODO(cushon): check package?
426e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon          if (!classTy.name().equals("String")) {
427e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon            throw new AssertionError(classTy);
428e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon          }
429e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon          return expr.asString();
430e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        }
431e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      default:
432e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        throw new AssertionError(t.ty().kind());
433e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    }
434e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  }
435e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon
436e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  static Const.Value add(Const.Value a, Const.Value b) {
437e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    if (a.constantTypeKind() == TurbineConstantTypeKind.STRING
438e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        || b.constantTypeKind() == TurbineConstantTypeKind.STRING) {
439e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      return new Const.StringValue(a.asString().value() + b.asString().value());
440e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    }
441e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    TurbineConstantTypeKind type = promoteBinary(a, b);
442e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    a = coerce(a, type);
443e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    b = coerce(b, type);
444e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    switch (type) {
445e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case INT:
446e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.IntValue(a.asInteger().value() + b.asInteger().value());
447e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case LONG:
448e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.LongValue(a.asLong().value() + b.asLong().value());
449e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case FLOAT:
450e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.FloatValue(a.asFloat().value() + b.asFloat().value());
451e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case DOUBLE:
452e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.DoubleValue(a.asDouble().value() + b.asDouble().value());
453e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      default:
454e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        throw new AssertionError(type);
455e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    }
456e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  }
457e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon
458e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  static Const.Value subtract(Const.Value a, Const.Value b) {
459e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    TurbineConstantTypeKind type = promoteBinary(a, b);
460e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    a = coerce(a, type);
461e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    b = coerce(b, type);
462e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    switch (type) {
463e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case INT:
464e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.IntValue(a.asInteger().value() - b.asInteger().value());
465e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case LONG:
466e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.LongValue(a.asLong().value() - b.asLong().value());
467e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case FLOAT:
468e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.FloatValue(a.asFloat().value() - b.asFloat().value());
469e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case DOUBLE:
470e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.DoubleValue(a.asDouble().value() - b.asDouble().value());
471e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      default:
472e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        throw new AssertionError(type);
473e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    }
474e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  }
475e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon
476e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  static Const.Value mult(Const.Value a, Const.Value b) {
477e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    TurbineConstantTypeKind type = promoteBinary(a, b);
478e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    a = coerce(a, type);
479e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    b = coerce(b, type);
480e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    switch (type) {
481e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case INT:
482e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.IntValue(a.asInteger().value() * b.asInteger().value());
483e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case LONG:
484e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.LongValue(a.asLong().value() * b.asLong().value());
485e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case FLOAT:
486e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.FloatValue(a.asFloat().value() * b.asFloat().value());
487e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case DOUBLE:
488e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.DoubleValue(a.asDouble().value() * b.asDouble().value());
489e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      default:
490e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        throw new AssertionError(type);
491e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    }
492e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  }
493e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon
494e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  static Const.Value divide(Const.Value a, Const.Value b) {
495e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    TurbineConstantTypeKind type = promoteBinary(a, b);
496e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    a = coerce(a, type);
497e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    b = coerce(b, type);
498e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    switch (type) {
499e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case INT:
500e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.IntValue(a.asInteger().value() / b.asInteger().value());
501e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case LONG:
502e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.LongValue(a.asLong().value() / b.asLong().value());
503e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case FLOAT:
504e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.FloatValue(a.asFloat().value() / b.asFloat().value());
505e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case DOUBLE:
506e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.DoubleValue(a.asDouble().value() / b.asDouble().value());
507e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      default:
508e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        throw new AssertionError(type);
509e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    }
510e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  }
511e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon
512e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  static Const.Value mod(Const.Value a, Const.Value b) {
513e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    TurbineConstantTypeKind type = promoteBinary(a, b);
514e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    a = coerce(a, type);
515e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    b = coerce(b, type);
516e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    switch (type) {
517e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case INT:
518e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.IntValue(a.asInteger().value() % b.asInteger().value());
519e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case LONG:
520e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.LongValue(a.asLong().value() % b.asLong().value());
521e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case FLOAT:
522e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.FloatValue(a.asFloat().value() % b.asFloat().value());
523e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case DOUBLE:
524e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.DoubleValue(a.asDouble().value() % b.asDouble().value());
525e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      default:
526e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        throw new AssertionError(type);
527e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    }
528e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  }
529e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon
530e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  static final int INT_SHIFT_MASK = 0b11111;
531e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon
532e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  static final int LONG_SHIFT_MASK = 0b111111;
533e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon
534e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  static Const.Value shiftLeft(Const.Value a, Const.Value b) {
535e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    a = promoteUnary(a);
536e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    b = promoteUnary(b);
537e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    switch (a.constantTypeKind()) {
538e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case INT:
539e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.IntValue(
540e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon            a.asInteger().value() << (b.asInteger().value() & INT_SHIFT_MASK));
541e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case LONG:
542e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.LongValue(a.asLong().value() << (b.asInteger().value() & LONG_SHIFT_MASK));
543e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      default:
544e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        throw new AssertionError(a.constantTypeKind());
545e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    }
546e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  }
547e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon
548e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  static Const.Value shiftRight(Const.Value a, Const.Value b) {
549e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    a = promoteUnary(a);
550e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    b = promoteUnary(b);
551e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    switch (a.constantTypeKind()) {
552e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case INT:
553e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.IntValue(
554e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon            a.asInteger().value() >> (b.asInteger().value() & INT_SHIFT_MASK));
555e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case LONG:
556e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.LongValue(a.asLong().value() >> (b.asInteger().value() & LONG_SHIFT_MASK));
557e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      default:
558e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        throw new AssertionError(a.constantTypeKind());
559e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    }
560e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  }
561e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon
562e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  static Const.Value unsignedShiftRight(Const.Value a, Const.Value b) {
563e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    a = promoteUnary(a);
564e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    b = promoteUnary(b);
565e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    switch (a.constantTypeKind()) {
566e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case INT:
567e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.IntValue(
568e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon            a.asInteger().value() >>> (b.asInteger().value() & INT_SHIFT_MASK));
569e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case LONG:
570e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.LongValue(
571e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon            a.asLong().value() >>> (b.asInteger().value() & LONG_SHIFT_MASK));
572e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      default:
573e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        throw new AssertionError(a.constantTypeKind());
574e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    }
575e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  }
576e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon
577e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  static Const.Value lessThan(Const.Value a, Const.Value b) {
578e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    TurbineConstantTypeKind type = promoteBinary(a, b);
579e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    a = coerce(a, type);
580e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    b = coerce(b, type);
581e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    switch (type) {
582e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case INT:
583e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(a.asInteger().value() < b.asInteger().value());
584e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case LONG:
585e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(a.asLong().value() < b.asLong().value());
586e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case FLOAT:
587e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(a.asFloat().value() < b.asFloat().value());
588e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case DOUBLE:
589e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(a.asDouble().value() < b.asDouble().value());
590e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      default:
591e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        throw new AssertionError(type);
592e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    }
593e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  }
594e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon
595e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  static Const.Value lessThanEqual(Const.Value a, Const.Value b) {
596e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    TurbineConstantTypeKind type = promoteBinary(a, b);
597e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    a = coerce(a, type);
598e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    b = coerce(b, type);
599e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    switch (type) {
600e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case INT:
601e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(a.asInteger().value() <= b.asInteger().value());
602e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case LONG:
603e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(a.asLong().value() <= b.asLong().value());
604e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case FLOAT:
605e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(a.asFloat().value() <= b.asFloat().value());
606e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case DOUBLE:
607e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(a.asDouble().value() <= b.asDouble().value());
608e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      default:
609e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        throw new AssertionError(type);
610e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    }
611e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  }
612e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon
613e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  static Const.Value greaterThan(Const.Value a, Const.Value b) {
614e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    TurbineConstantTypeKind type = promoteBinary(a, b);
615e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    a = coerce(a, type);
616e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    b = coerce(b, type);
617e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    switch (type) {
618e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case INT:
619e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(a.asInteger().value() > b.asInteger().value());
620e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case LONG:
621e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(a.asLong().value() > b.asLong().value());
622e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case FLOAT:
623e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(a.asFloat().value() > b.asFloat().value());
624e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case DOUBLE:
625e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(a.asDouble().value() > b.asDouble().value());
626e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      default:
627e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        throw new AssertionError(type);
628e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    }
629e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  }
630e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon
631e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  static Const.Value greaterThanEqual(Const.Value a, Const.Value b) {
632e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    TurbineConstantTypeKind type = promoteBinary(a, b);
633e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    a = coerce(a, type);
634e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    b = coerce(b, type);
635e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    switch (type) {
636e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case INT:
637e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(a.asInteger().value() >= b.asInteger().value());
638e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case LONG:
639e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(a.asLong().value() >= b.asLong().value());
640e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case FLOAT:
641e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(a.asFloat().value() >= b.asFloat().value());
642e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case DOUBLE:
643e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(a.asDouble().value() >= b.asDouble().value());
644e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      default:
645e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        throw new AssertionError(type);
646e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    }
647e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  }
648e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon
649e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  static Const.Value equal(Const.Value a, Const.Value b) {
650e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    switch (a.constantTypeKind()) {
651e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case STRING:
652e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(a.asString().value().equals(b.asString().value()));
653e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case BOOLEAN:
654e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(a.asBoolean().value() == b.asBoolean().value());
655e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      default:
656e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        break;
657e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    }
658e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    TurbineConstantTypeKind type = promoteBinary(a, b);
659e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    a = coerce(a, type);
660e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    b = coerce(b, type);
661e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    switch (type) {
662e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case INT:
663e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(a.asInteger().value() == b.asInteger().value());
664e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case LONG:
665e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(a.asLong().value() == b.asLong().value());
666e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case FLOAT:
667e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(a.asFloat().value() == b.asFloat().value());
668e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case DOUBLE:
669e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(a.asDouble().value() == b.asDouble().value());
670e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      default:
671e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        throw new AssertionError(type);
672e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    }
673e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  }
674e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon
675e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  static Const.Value notEqual(Const.Value a, Const.Value b) {
676e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    switch (a.constantTypeKind()) {
677e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case STRING:
678e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(!a.asString().value().equals(b.asString().value()));
679e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case BOOLEAN:
680e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(a.asBoolean().value() != b.asBoolean().value());
681e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      default:
682e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        break;
683e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    }
684e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    TurbineConstantTypeKind type = promoteBinary(a, b);
685e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    a = coerce(a, type);
686e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    b = coerce(b, type);
687e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    switch (type) {
688e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case INT:
689e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(a.asInteger().value() != b.asInteger().value());
690e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case LONG:
691e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(a.asLong().value() != b.asLong().value());
692e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case FLOAT:
693e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(a.asFloat().value() != b.asFloat().value());
694e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case DOUBLE:
695e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(a.asDouble().value() != b.asDouble().value());
696e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      default:
697e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        throw new AssertionError(type);
698e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    }
699e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  }
700e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon
701e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  static Const.Value bitwiseAnd(Const.Value a, Const.Value b) {
702e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    switch (a.constantTypeKind()) {
703e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case BOOLEAN:
704e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(a.asBoolean().value() & b.asBoolean().value());
705e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      default:
706e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        break;
707e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    }
708e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    TurbineConstantTypeKind type = promoteBinary(a, b);
709e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    a = coerce(a, type);
710e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    b = coerce(b, type);
711e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    switch (type) {
712e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case INT:
713e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.IntValue(a.asInteger().value() & b.asInteger().value());
714e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case LONG:
715e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.LongValue(a.asLong().value() & b.asLong().value());
716e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      default:
717e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        throw new AssertionError(type);
718e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    }
719e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  }
720e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon
721e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  static Const.Value bitwiseOr(Const.Value a, Const.Value b) {
722e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    switch (a.constantTypeKind()) {
723e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case BOOLEAN:
724e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(a.asBoolean().value() | b.asBoolean().value());
725e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      default:
726e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        break;
727e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    }
728e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    TurbineConstantTypeKind type = promoteBinary(a, b);
729e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    a = coerce(a, type);
730e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    b = coerce(b, type);
731e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    switch (type) {
732e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case INT:
733e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.IntValue(a.asInteger().value() | b.asInteger().value());
734e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case LONG:
735e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.LongValue(a.asLong().value() | b.asLong().value());
736e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      default:
737e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        throw new AssertionError(type);
738e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    }
739e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  }
740e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon
741e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  static Const.Value bitwiseXor(Const.Value a, Const.Value b) {
742e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    switch (a.constantTypeKind()) {
743e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case BOOLEAN:
744e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(a.asBoolean().value() ^ b.asBoolean().value());
745e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      default:
746e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        break;
747e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    }
748e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    TurbineConstantTypeKind type = promoteBinary(a, b);
749e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    a = coerce(a, type);
750e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    b = coerce(b, type);
751e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    switch (type) {
752e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case INT:
753e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.IntValue(a.asInteger().value() ^ b.asInteger().value());
754e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case LONG:
755e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.LongValue(a.asLong().value() ^ b.asLong().value());
756e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      default:
757e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        throw new AssertionError(type);
758e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    }
759e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  }
760e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon
761e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  private Const.Value evalBinary(Binary t) {
762e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    Const.Value lhs = evalValue(t.lhs());
763e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    Const.Value rhs = evalValue(t.rhs());
764806d6a5f4a319f2c00baf2334732024c5bdcacb5cushon    if (lhs == null || rhs == null) {
765806d6a5f4a319f2c00baf2334732024c5bdcacb5cushon      return null;
766806d6a5f4a319f2c00baf2334732024c5bdcacb5cushon    }
767e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    switch (t.op()) {
768e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case PLUS:
769e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return add(lhs, rhs);
770e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case MINUS:
771e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return subtract(lhs, rhs);
772e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case MULT:
773e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return mult(lhs, rhs);
774e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case DIVIDE:
775e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return divide(lhs, rhs);
776e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case MODULO:
777e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return mod(lhs, rhs);
778e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case SHIFT_LEFT:
779e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return shiftLeft(lhs, rhs);
780e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case SHIFT_RIGHT:
781e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return shiftRight(lhs, rhs);
782e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case UNSIGNED_SHIFT_RIGHT:
783e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return unsignedShiftRight(lhs, rhs);
784e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case LESS_THAN:
785e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return lessThan(lhs, rhs);
786e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case GREATER_THAN:
787e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return greaterThan(lhs, rhs);
788e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case LESS_THAN_EQ:
789e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return lessThanEqual(lhs, rhs);
790e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case GREATER_THAN_EQ:
791e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return greaterThanEqual(lhs, rhs);
792e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case EQUAL:
793e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return equal(lhs, rhs);
794e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case NOT_EQUAL:
795e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return notEqual(lhs, rhs);
796e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case AND:
797e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(lhs.asBoolean().value() && rhs.asBoolean().value());
798e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case OR:
799e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return new Const.BooleanValue(lhs.asBoolean().value() || rhs.asBoolean().value());
800e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case BITWISE_AND:
801e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return bitwiseAnd(lhs, rhs);
802e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case BITWISE_XOR:
803e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return bitwiseXor(lhs, rhs);
804e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case BITWISE_OR:
805e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return bitwiseOr(lhs, rhs);
806e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      default:
807e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        throw new AssertionError(t.op());
808e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    }
809e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  }
810e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon
811e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  private static Const.Value promoteUnary(Const.Value v) {
812e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    switch (v.constantTypeKind()) {
813e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case CHAR:
814e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case SHORT:
815e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case BYTE:
816e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return v.asInteger();
817e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case INT:
818e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case LONG:
819e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case FLOAT:
820e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case DOUBLE:
821e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        return v;
822e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      default:
823e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        throw new AssertionError(v.constantTypeKind());
824e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    }
825e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  }
826e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon
827e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon  private static TurbineConstantTypeKind promoteBinary(Const.Value a, Const.Value b) {
828e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    a = promoteUnary(a);
829e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    b = promoteUnary(b);
830e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    switch (a.constantTypeKind()) {
831e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case INT:
832e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        switch (b.constantTypeKind()) {
833e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon          case INT:
834e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon          case LONG:
835e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon          case DOUBLE:
836e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon          case FLOAT:
837e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon            return b.constantTypeKind();
838e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon          default:
839e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon            throw new AssertionError(b.constantTypeKind());
840e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        }
841e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case LONG:
842e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        switch (b.constantTypeKind()) {
843e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon          case INT:
844e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon            return TurbineConstantTypeKind.LONG;
845e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon          case LONG:
846e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon          case DOUBLE:
847e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon          case FLOAT:
848e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon            return b.constantTypeKind();
849e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon          default:
850e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon            throw new AssertionError(b.constantTypeKind());
851e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        }
852e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case FLOAT:
853e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        switch (b.constantTypeKind()) {
854e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon          case INT:
855e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon          case LONG:
856e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon          case FLOAT:
857e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon            return TurbineConstantTypeKind.FLOAT;
858e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon          case DOUBLE:
859e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon            return TurbineConstantTypeKind.DOUBLE;
860e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon          default:
861e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon            throw new AssertionError(b.constantTypeKind());
862e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        }
863e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      case DOUBLE:
864e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        switch (b.constantTypeKind()) {
865e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon          case INT:
866e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon          case LONG:
867e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon          case FLOAT:
868e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon          case DOUBLE:
869e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon            return TurbineConstantTypeKind.DOUBLE;
870e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon          default:
871e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon            throw new AssertionError(b.constantTypeKind());
872e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        }
873e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon      default:
874e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon        throw new AssertionError(a.constantTypeKind());
875e00c9907c7a2be5cac0133c972a3037c9a02d6a5cushon    }
876bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon  }
8774d51bb2c21dffcb267e9b3a3538117adc6009e57cushon
878cdefacdcf613684b385797d2d4340f3fa7dcce2dcushon  ImmutableList<AnnoInfo> evaluateAnnotations(ImmutableList<AnnoInfo> annotations) {
879cdefacdcf613684b385797d2d4340f3fa7dcce2dcushon    ImmutableList.Builder<AnnoInfo> result = ImmutableList.builder();
880cdefacdcf613684b385797d2d4340f3fa7dcce2dcushon    for (AnnoInfo annotation : annotations) {
88133e253bd3b1ce0d4939345229e78523063527eebcushon      result.add(evaluateAnnotation(annotation));
882cdefacdcf613684b385797d2d4340f3fa7dcce2dcushon    }
883cdefacdcf613684b385797d2d4340f3fa7dcce2dcushon    return result.build();
884cdefacdcf613684b385797d2d4340f3fa7dcce2dcushon  }
885cdefacdcf613684b385797d2d4340f3fa7dcce2dcushon
8864d51bb2c21dffcb267e9b3a3538117adc6009e57cushon  /**
8874d51bb2c21dffcb267e9b3a3538117adc6009e57cushon   * Evaluates annotation arguments given the symbol of the annotation declaration and a list of
8884d51bb2c21dffcb267e9b3a3538117adc6009e57cushon   * expression trees.
8894d51bb2c21dffcb267e9b3a3538117adc6009e57cushon   */
89033e253bd3b1ce0d4939345229e78523063527eebcushon  AnnoInfo evaluateAnnotation(AnnoInfo info) {
8914d51bb2c21dffcb267e9b3a3538117adc6009e57cushon    Map<String, Type> template = new LinkedHashMap<>();
89233e253bd3b1ce0d4939345229e78523063527eebcushon    for (MethodInfo method : env.get(info.sym()).methods()) {
8934d51bb2c21dffcb267e9b3a3538117adc6009e57cushon      template.put(method.name(), method.returnType());
8944d51bb2c21dffcb267e9b3a3538117adc6009e57cushon    }
8954d51bb2c21dffcb267e9b3a3538117adc6009e57cushon
8964d51bb2c21dffcb267e9b3a3538117adc6009e57cushon    ImmutableMap.Builder<String, Const> values = ImmutableMap.builder();
89733e253bd3b1ce0d4939345229e78523063527eebcushon    for (Expression arg : info.args()) {
8984d51bb2c21dffcb267e9b3a3538117adc6009e57cushon      Expression expr;
8994d51bb2c21dffcb267e9b3a3538117adc6009e57cushon      String key;
9004d51bb2c21dffcb267e9b3a3538117adc6009e57cushon      if (arg.kind() == Tree.Kind.ASSIGN) {
9014d51bb2c21dffcb267e9b3a3538117adc6009e57cushon        Tree.Assign assign = (Tree.Assign) arg;
9024d51bb2c21dffcb267e9b3a3538117adc6009e57cushon        key = assign.name();
9034d51bb2c21dffcb267e9b3a3538117adc6009e57cushon        expr = assign.expr();
9044d51bb2c21dffcb267e9b3a3538117adc6009e57cushon      } else {
9054d51bb2c21dffcb267e9b3a3538117adc6009e57cushon        // expand the implicit 'value' name; `@Foo(42)` is sugar for `@Foo(value=42)`
9064d51bb2c21dffcb267e9b3a3538117adc6009e57cushon        key = "value";
9074d51bb2c21dffcb267e9b3a3538117adc6009e57cushon        expr = arg;
9084d51bb2c21dffcb267e9b3a3538117adc6009e57cushon      }
9094d51bb2c21dffcb267e9b3a3538117adc6009e57cushon      Type ty = template.get(key);
910b0445ae9c37a1fab07fb5f234653e8ea072bf9fccushon      if (ty == null) {
911b25a536a58cfc542d70a118aebc30d3a9dea5654cushon        throw error(arg.position(), ErrorKind.CANNOT_RESOLVE, key);
912b0445ae9c37a1fab07fb5f234653e8ea072bf9fccushon      }
9134d51bb2c21dffcb267e9b3a3538117adc6009e57cushon      Const value = evalAnnotationValue(expr, ty);
9143de8ed9a49a939e11961146bf5b6a41c20dc7f79cushon      if (value == null) {
9153de8ed9a49a939e11961146bf5b6a41c20dc7f79cushon        throw error(expr.position(), ErrorKind.EXPRESSION_ERROR);
9163de8ed9a49a939e11961146bf5b6a41c20dc7f79cushon      }
9174d51bb2c21dffcb267e9b3a3538117adc6009e57cushon      values.put(key, value);
9184d51bb2c21dffcb267e9b3a3538117adc6009e57cushon    }
91933e253bd3b1ce0d4939345229e78523063527eebcushon    return info.withValues(values.build());
9204d51bb2c21dffcb267e9b3a3538117adc6009e57cushon  }
9214d51bb2c21dffcb267e9b3a3538117adc6009e57cushon
92205878b6cb86f32245891d6e4504a8b1e7fcd2155cushon  private AnnotationValue evalAnno(Tree.Anno t) {
92316d4fb60dd03fe84f50a96d42db6180a286fc3dbcushon    LookupResult result = scope.lookup(new LookupKey(t.name()));
9243088f83b806b82d866d119e344da274105f42821cushon    ClassSymbol sym = (ClassSymbol) result.sym();
9253088f83b806b82d866d119e344da274105f42821cushon    for (String name : result.remaining()) {
926c4fcb03ad72af457d0448f4207085c2a60b4ae52cushon      sym = Resolve.resolve(env, sym, sym, name);
9273088f83b806b82d866d119e344da274105f42821cushon    }
92833e253bd3b1ce0d4939345229e78523063527eebcushon    AnnoInfo annoInfo = evaluateAnnotation(new AnnoInfo(base.source(), sym, t, null));
92905878b6cb86f32245891d6e4504a8b1e7fcd2155cushon    return new AnnotationValue(annoInfo.sym(), annoInfo.values());
9303088f83b806b82d866d119e344da274105f42821cushon  }
9313088f83b806b82d866d119e344da274105f42821cushon
9323088f83b806b82d866d119e344da274105f42821cushon  private Const.ArrayInitValue evalArrayInit(ArrayInit t) {
9333088f83b806b82d866d119e344da274105f42821cushon    ImmutableList.Builder<Const> elements = ImmutableList.builder();
9343088f83b806b82d866d119e344da274105f42821cushon    for (Expression e : t.exprs()) {
935806d6a5f4a319f2c00baf2334732024c5bdcacb5cushon      Const arg = eval(e);
936806d6a5f4a319f2c00baf2334732024c5bdcacb5cushon      if (arg == null) {
937806d6a5f4a319f2c00baf2334732024c5bdcacb5cushon        return null;
938806d6a5f4a319f2c00baf2334732024c5bdcacb5cushon      }
939806d6a5f4a319f2c00baf2334732024c5bdcacb5cushon      elements.add(arg);
9404d51bb2c21dffcb267e9b3a3538117adc6009e57cushon    }
9413088f83b806b82d866d119e344da274105f42821cushon    return new Const.ArrayInitValue(elements.build());
9424d51bb2c21dffcb267e9b3a3538117adc6009e57cushon  }
9434d51bb2c21dffcb267e9b3a3538117adc6009e57cushon
9443088f83b806b82d866d119e344da274105f42821cushon  Const evalAnnotationValue(Tree tree, Type ty) {
945b0445ae9c37a1fab07fb5f234653e8ea072bf9fccushon    if (ty == null) {
946b25a536a58cfc542d70a118aebc30d3a9dea5654cushon      throw error(tree.position(), ErrorKind.EXPRESSION_ERROR);
947b0445ae9c37a1fab07fb5f234653e8ea072bf9fccushon    }
9484d51bb2c21dffcb267e9b3a3538117adc6009e57cushon    Const value = eval(tree);
949a5453051f0c8b71a833f6dc73caaea43bd24a0dbcushon    if (value == null) {
950a5453051f0c8b71a833f6dc73caaea43bd24a0dbcushon      throw error(tree.position(), ErrorKind.EXPRESSION_ERROR);
951a5453051f0c8b71a833f6dc73caaea43bd24a0dbcushon    }
9524d51bb2c21dffcb267e9b3a3538117adc6009e57cushon    switch (ty.tyKind()) {
9534d51bb2c21dffcb267e9b3a3538117adc6009e57cushon      case PRIM_TY:
9544d51bb2c21dffcb267e9b3a3538117adc6009e57cushon        return coerce((Const.Value) value, ((Type.PrimTy) ty).primkind());
9554d51bb2c21dffcb267e9b3a3538117adc6009e57cushon      case CLASS_TY:
9564d51bb2c21dffcb267e9b3a3538117adc6009e57cushon      case TY_VAR:
9574d51bb2c21dffcb267e9b3a3538117adc6009e57cushon        return value;
9584d51bb2c21dffcb267e9b3a3538117adc6009e57cushon      case ARRAY_TY:
9594d51bb2c21dffcb267e9b3a3538117adc6009e57cushon        {
960d161fb6fcbd2e8ab64abf467823920398ad34b63cushon          Type elementType = ((Type.ArrayTy) ty).elementType();
961d161fb6fcbd2e8ab64abf467823920398ad34b63cushon          ImmutableList<Const> elements =
962d161fb6fcbd2e8ab64abf467823920398ad34b63cushon              value.kind() == Const.Kind.ARRAY
963d161fb6fcbd2e8ab64abf467823920398ad34b63cushon                  ? ((Const.ArrayInitValue) value).elements()
964d161fb6fcbd2e8ab64abf467823920398ad34b63cushon                  : ImmutableList.of(value);
965d161fb6fcbd2e8ab64abf467823920398ad34b63cushon          ImmutableList.Builder<Const> coerced = ImmutableList.builder();
966d161fb6fcbd2e8ab64abf467823920398ad34b63cushon          for (Const element : elements) {
967d161fb6fcbd2e8ab64abf467823920398ad34b63cushon            coerced.add(cast(elementType, element));
9684d51bb2c21dffcb267e9b3a3538117adc6009e57cushon          }
969d161fb6fcbd2e8ab64abf467823920398ad34b63cushon          return new Const.ArrayInitValue(coerced.build());
9704d51bb2c21dffcb267e9b3a3538117adc6009e57cushon        }
9714d51bb2c21dffcb267e9b3a3538117adc6009e57cushon      default:
9724d51bb2c21dffcb267e9b3a3538117adc6009e57cushon        throw new AssertionError(ty.tyKind());
9734d51bb2c21dffcb267e9b3a3538117adc6009e57cushon    }
9744d51bb2c21dffcb267e9b3a3538117adc6009e57cushon  }
975b0445ae9c37a1fab07fb5f234653e8ea072bf9fccushon
976b25a536a58cfc542d70a118aebc30d3a9dea5654cushon  private TurbineError error(int position, ErrorKind kind, Object... args) {
977b25a536a58cfc542d70a118aebc30d3a9dea5654cushon    return TurbineError.format(base.source(), position, kind, args);
978b0445ae9c37a1fab07fb5f234653e8ea072bf9fccushon  }
9799f3e44c5390f7c1845078865d0ef07357e949080cushon
9809f3e44c5390f7c1845078865d0ef07357e949080cushon  public Const.Value evalFieldInitializer(Expression expression, Type type) {
9819f3e44c5390f7c1845078865d0ef07357e949080cushon    Const value = eval(expression);
9829f3e44c5390f7c1845078865d0ef07357e949080cushon    if (value == null || value.kind() != Const.Kind.PRIMITIVE) {
9839f3e44c5390f7c1845078865d0ef07357e949080cushon      return null;
9849f3e44c5390f7c1845078865d0ef07357e949080cushon    }
9859f3e44c5390f7c1845078865d0ef07357e949080cushon    return (Const.Value) cast(type, value);
9869f3e44c5390f7c1845078865d0ef07357e949080cushon  }
987bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon}
988