Home | History | Annotate | Download | only in type
      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.type;
     18 
     19 import com.google.common.base.Joiner;
     20 import com.google.common.base.Preconditions;
     21 import com.google.common.collect.ImmutableList;
     22 import com.google.turbine.binder.sym.ClassSymbol;
     23 import com.google.turbine.binder.sym.TyVarSymbol;
     24 import com.google.turbine.model.TurbineConstantTypeKind;
     25 import java.util.Arrays;
     26 
     27 /** JLS 4 types. */
     28 public interface Type {
     29 
     30   /** A type kind. */
     31   enum TyKind {
     32     /** A primitive type. */
     33     PRIM_TY,
     34     /**
     35      * The void type.
     36      *
     37      * <p>It isn't actually a type in the spec, but it's included here for convenience.
     38      */
     39     VOID_TY,
     40     /** A class type. */
     41     CLASS_TY,
     42     /** An array type. */
     43     ARRAY_TY,
     44     /** A type variable type. */
     45     TY_VAR,
     46     /** A wildcard type. */
     47     WILD_TY
     48   }
     49 
     50   /** The type kind. */
     51   TyKind tyKind();
     52 
     53   /** The void type. */
     54   Type VOID =
     55       new Type() {
     56         @Override
     57         public TyKind tyKind() {
     58           return TyKind.VOID_TY;
     59         }
     60       };
     61 
     62   /** A class type. */
     63   class ClassTy implements Type {
     64 
     65     /**
     66      * The {@link ClassTy} for {@code java.lang.Object}. There's nothing special about this
     67      * instance, it's just to avoid some boilerplate.
     68      */
     69     public static final ClassTy OBJECT = asNonParametricClassTy(ClassSymbol.OBJECT);
     70 
     71     /** The {@link ClassTy} for {@code java.lang.String}. */
     72     public static final ClassTy STRING = asNonParametricClassTy(ClassSymbol.STRING);
     73 
     74     /** Returns a {@link ClassTy} with no type arguments for the given {@link ClassSymbol}. */
     75     public static ClassTy asNonParametricClassTy(ClassSymbol i) {
     76       return new ClassTy(
     77           Arrays.asList(new SimpleClassTy(i, ImmutableList.of(), ImmutableList.of())));
     78     }
     79 
     80     public final ImmutableList<SimpleClassTy> classes;
     81 
     82     /**
     83      * A class type. Qualified types are repesented as a list tuples, each of which contains a
     84      * {@link ClassSymbol} and an optional list of type arguments.
     85      *
     86      * @param classes components of a qualified class type, possibly with type arguments.
     87      */
     88     public ClassTy(Iterable<SimpleClassTy> classes) {
     89       this.classes = ImmutableList.copyOf(classes);
     90     }
     91 
     92     @Override
     93     public TyKind tyKind() {
     94       return TyKind.CLASS_TY;
     95     }
     96 
     97     /** The class symbol. */
     98     public ClassSymbol sym() {
     99       return classes.get(classes.size() - 1).sym;
    100     }
    101 
    102     @Override
    103     public String toString() {
    104       StringBuilder sb = new StringBuilder();
    105       boolean first = true;
    106       for (SimpleClassTy c : classes) {
    107         if (!first) {
    108           sb.append('.');
    109           sb.append(c.sym.toString().substring(c.sym.toString().lastIndexOf('$') + 1));
    110         } else {
    111           sb.append(c.sym);
    112         }
    113         if (!c.targs.isEmpty()) {
    114           sb.append('<');
    115           Joiner.on(',').appendTo(sb, c.targs);
    116           sb.append('>');
    117         }
    118         first = false;
    119       }
    120       return sb.toString();
    121     }
    122 
    123     /** One element of a qualified {@link ClassTy}. */
    124     public static class SimpleClassTy {
    125 
    126       private final ClassSymbol sym;
    127       private final ImmutableList<Type> targs;
    128       private final ImmutableList<AnnoInfo> annos;
    129 
    130       public SimpleClassTy(
    131           ClassSymbol sym, ImmutableList<Type> targs, ImmutableList<AnnoInfo> annos) {
    132         Preconditions.checkNotNull(sym);
    133         Preconditions.checkNotNull(targs);
    134         this.sym = sym;
    135         this.targs = targs;
    136         this.annos = annos;
    137       }
    138 
    139       /** The class symbol of the element. */
    140       public ClassSymbol sym() {
    141         return sym;
    142       }
    143 
    144       /** The type arguments. */
    145       public ImmutableList<Type> targs() {
    146         return targs;
    147       }
    148 
    149       /** The type annotations. */
    150       public ImmutableList<AnnoInfo> annos() {
    151         return annos;
    152       }
    153     }
    154   }
    155 
    156   /** An array type. */
    157   class ArrayTy implements Type {
    158 
    159     private final Type elem;
    160     private final ImmutableList<AnnoInfo> annos;
    161 
    162     public ArrayTy(Type elem, ImmutableList<AnnoInfo> annos) {
    163       this.elem = elem;
    164       this.annos = annos;
    165     }
    166 
    167     /** The element type of the array. */
    168     public Type elementType() {
    169       return elem;
    170     }
    171 
    172     @Override
    173     public TyKind tyKind() {
    174       return TyKind.ARRAY_TY;
    175     }
    176 
    177     /** The type annotations. */
    178     public ImmutableList<AnnoInfo> annos() {
    179       return annos;
    180     }
    181   }
    182 
    183   /** A type variable. */
    184   class TyVar implements Type {
    185 
    186     private final TyVarSymbol sym;
    187     private final ImmutableList<AnnoInfo> annos;
    188 
    189     public TyVar(TyVarSymbol sym, ImmutableList<AnnoInfo> annos) {
    190       this.sym = sym;
    191       this.annos = annos;
    192     }
    193 
    194     /** The type variable's symbol. */
    195     public TyVarSymbol sym() {
    196       return sym;
    197     }
    198 
    199     @Override
    200     public TyKind tyKind() {
    201       return TyKind.TY_VAR;
    202     }
    203 
    204     @Override
    205     public String toString() {
    206       return sym.owner() + "#" + sym.name();
    207     }
    208 
    209     /** The type annotations. */
    210     public ImmutableList<AnnoInfo> annos() {
    211       return annos;
    212     }
    213   }
    214 
    215   /** A primitive type. */
    216   class PrimTy implements Type {
    217 
    218     private final TurbineConstantTypeKind primtkind;
    219     private final ImmutableList<AnnoInfo> annos;
    220 
    221     public PrimTy(TurbineConstantTypeKind tykind, ImmutableList<AnnoInfo> annos) {
    222       this.primtkind = tykind;
    223       this.annos = annos;
    224     }
    225 
    226     /** The primtive type kind. */
    227     public TurbineConstantTypeKind primkind() {
    228       return primtkind;
    229     }
    230 
    231     @Override
    232     public TyKind tyKind() {
    233       return TyKind.PRIM_TY;
    234     }
    235 
    236     /** The type annotations. */
    237     public ImmutableList<AnnoInfo> annos() {
    238       return annos;
    239     }
    240   }
    241 
    242   /** A wildcard type, valid only inside (possibly nested) type arguments. */
    243   abstract class WildTy implements Type {
    244 
    245     public enum BoundKind {
    246       NONE,
    247       UPPER,
    248       LOWER
    249     }
    250 
    251     public abstract BoundKind boundKind();
    252 
    253     public abstract Type bound();
    254 
    255     /** The type annotations. */
    256     public abstract ImmutableList<AnnoInfo> annotations();
    257 
    258     @Override
    259     public TyKind tyKind() {
    260       return TyKind.WILD_TY;
    261     }
    262   }
    263 
    264   /** An upper-bounded wildcard type. */
    265   class WildUpperBoundedTy extends WildTy {
    266 
    267     public final Type bound;
    268     private final ImmutableList<AnnoInfo> annotations;
    269 
    270     public WildUpperBoundedTy(Type bound, ImmutableList<AnnoInfo> annotations) {
    271       this.bound = bound;
    272       this.annotations = annotations;
    273     }
    274 
    275     /** The upper bound. */
    276     @Override
    277     public Type bound() {
    278       return bound;
    279     }
    280 
    281     @Override
    282     public ImmutableList<AnnoInfo> annotations() {
    283       return annotations;
    284     }
    285 
    286     @Override
    287     public BoundKind boundKind() {
    288       return BoundKind.UPPER;
    289     }
    290   }
    291 
    292   /** An lower-bounded wildcard type. */
    293   class WildLowerBoundedTy extends WildTy {
    294 
    295     public final Type bound;
    296     private final ImmutableList<AnnoInfo> annotations;
    297 
    298     public WildLowerBoundedTy(Type bound, ImmutableList<AnnoInfo> annotations) {
    299       this.bound = bound;
    300       this.annotations = annotations;
    301     }
    302 
    303     /** The lower bound. */
    304     @Override
    305     public Type bound() {
    306       return bound;
    307     }
    308 
    309     @Override
    310     public BoundKind boundKind() {
    311       return BoundKind.LOWER;
    312     }
    313 
    314     @Override
    315     public ImmutableList<AnnoInfo> annotations() {
    316       return annotations;
    317     }
    318   }
    319 
    320   /** An unbounded wildcard type. */
    321   class WildUnboundedTy extends WildTy {
    322 
    323     private final ImmutableList<AnnoInfo> annotations;
    324 
    325     public WildUnboundedTy(ImmutableList<AnnoInfo> annotations) {
    326       this.annotations = annotations;
    327     }
    328 
    329     @Override
    330     public BoundKind boundKind() {
    331       return BoundKind.NONE;
    332     }
    333 
    334     @Override
    335     public Type bound() {
    336       throw new IllegalStateException();
    337     }
    338 
    339     @Override
    340     public ImmutableList<AnnoInfo> annotations() {
    341       return annotations;
    342     }
    343   }
    344 }
    345