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