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