1d1a195115e72855d8928c07ff4a166759546ed23cushon/*
2d1a195115e72855d8928c07ff4a166759546ed23cushon * Copyright 2016 Google Inc. All Rights Reserved.
3d1a195115e72855d8928c07ff4a166759546ed23cushon *
4d1a195115e72855d8928c07ff4a166759546ed23cushon * Licensed under the Apache License, Version 2.0 (the "License");
5d1a195115e72855d8928c07ff4a166759546ed23cushon * you may not use this file except in compliance with the License.
6d1a195115e72855d8928c07ff4a166759546ed23cushon * You may obtain a copy of the License at
7d1a195115e72855d8928c07ff4a166759546ed23cushon *
8d1a195115e72855d8928c07ff4a166759546ed23cushon *     http://www.apache.org/licenses/LICENSE-2.0
9d1a195115e72855d8928c07ff4a166759546ed23cushon *
10d1a195115e72855d8928c07ff4a166759546ed23cushon * Unless required by applicable law or agreed to in writing, software
11d1a195115e72855d8928c07ff4a166759546ed23cushon * distributed under the License is distributed on an "AS IS" BASIS,
12d1a195115e72855d8928c07ff4a166759546ed23cushon * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d1a195115e72855d8928c07ff4a166759546ed23cushon * See the License for the specific language governing permissions and
14d1a195115e72855d8928c07ff4a166759546ed23cushon * limitations under the License.
15d1a195115e72855d8928c07ff4a166759546ed23cushon */
16d1a195115e72855d8928c07ff4a166759546ed23cushon
17d1a195115e72855d8928c07ff4a166759546ed23cushonpackage com.google.turbine.types;
18d1a195115e72855d8928c07ff4a166759546ed23cushon
19d1a195115e72855d8928c07ff4a166759546ed23cushonimport com.google.common.base.Function;
20d1a195115e72855d8928c07ff4a166759546ed23cushonimport com.google.common.collect.ImmutableList;
21d1a195115e72855d8928c07ff4a166759546ed23cushonimport com.google.turbine.binder.bound.SourceTypeBoundClass;
22d1a195115e72855d8928c07ff4a166759546ed23cushonimport com.google.turbine.binder.sym.TyVarSymbol;
23d1a195115e72855d8928c07ff4a166759546ed23cushonimport com.google.turbine.type.Type;
24d1a195115e72855d8928c07ff4a166759546ed23cushonimport com.google.turbine.type.Type.TyVar;
25d1a195115e72855d8928c07ff4a166759546ed23cushon
26d1a195115e72855d8928c07ff4a166759546ed23cushon/** Generic type erasure. */
27d1a195115e72855d8928c07ff4a166759546ed23cushonpublic class Erasure {
28d1a195115e72855d8928c07ff4a166759546ed23cushon  public static Type erase(Type ty, Function<TyVarSymbol, SourceTypeBoundClass.TyVarInfo> tenv) {
29d1a195115e72855d8928c07ff4a166759546ed23cushon    switch (ty.tyKind()) {
30d1a195115e72855d8928c07ff4a166759546ed23cushon      case PRIM_TY:
31d1a195115e72855d8928c07ff4a166759546ed23cushon      case VOID_TY:
32d1a195115e72855d8928c07ff4a166759546ed23cushon        return ty;
33d1a195115e72855d8928c07ff4a166759546ed23cushon      case CLASS_TY:
34d1a195115e72855d8928c07ff4a166759546ed23cushon        return eraseClassTy((Type.ClassTy) ty);
35d1a195115e72855d8928c07ff4a166759546ed23cushon      case ARRAY_TY:
36d1a195115e72855d8928c07ff4a166759546ed23cushon        return eraseArrayTy((Type.ArrayTy) ty, tenv);
37d1a195115e72855d8928c07ff4a166759546ed23cushon      case TY_VAR:
38d1a195115e72855d8928c07ff4a166759546ed23cushon        return eraseTyVar((TyVar) ty, tenv);
39d1a195115e72855d8928c07ff4a166759546ed23cushon      default:
40d1a195115e72855d8928c07ff4a166759546ed23cushon        throw new AssertionError(ty.tyKind());
41d1a195115e72855d8928c07ff4a166759546ed23cushon    }
42d1a195115e72855d8928c07ff4a166759546ed23cushon  }
43d1a195115e72855d8928c07ff4a166759546ed23cushon
44d1a195115e72855d8928c07ff4a166759546ed23cushon  private static Type eraseTyVar(
45d1a195115e72855d8928c07ff4a166759546ed23cushon      TyVar ty, Function<TyVarSymbol, SourceTypeBoundClass.TyVarInfo> tenv) {
46d1a195115e72855d8928c07ff4a166759546ed23cushon    SourceTypeBoundClass.TyVarInfo info = tenv.apply(ty.sym());
47d1a195115e72855d8928c07ff4a166759546ed23cushon    if (info.superClassBound() != null) {
48d1a195115e72855d8928c07ff4a166759546ed23cushon      return erase(info.superClassBound(), tenv);
49d1a195115e72855d8928c07ff4a166759546ed23cushon    }
50d1a195115e72855d8928c07ff4a166759546ed23cushon    if (!info.interfaceBounds().isEmpty()) {
51d1a195115e72855d8928c07ff4a166759546ed23cushon      return erase(info.interfaceBounds().get(0), tenv);
52d1a195115e72855d8928c07ff4a166759546ed23cushon    }
53d1a195115e72855d8928c07ff4a166759546ed23cushon    return Type.ClassTy.OBJECT;
54d1a195115e72855d8928c07ff4a166759546ed23cushon  }
55d1a195115e72855d8928c07ff4a166759546ed23cushon
567e2d4aea15dacf4732174504a7a08f9c6ae1ffb3cushon  private static Type.ArrayTy eraseArrayTy(
57d1a195115e72855d8928c07ff4a166759546ed23cushon      Type.ArrayTy ty, Function<TyVarSymbol, SourceTypeBoundClass.TyVarInfo> tenv) {
587e2d4aea15dacf4732174504a7a08f9c6ae1ffb3cushon    return new Type.ArrayTy(erase(ty.elementType(), tenv), ty.annos());
59d1a195115e72855d8928c07ff4a166759546ed23cushon  }
60d1a195115e72855d8928c07ff4a166759546ed23cushon
617e2d4aea15dacf4732174504a7a08f9c6ae1ffb3cushon  public static Type.ClassTy eraseClassTy(Type.ClassTy ty) {
62d1a195115e72855d8928c07ff4a166759546ed23cushon    ImmutableList.Builder<Type.ClassTy.SimpleClassTy> classes = ImmutableList.builder();
63d1a195115e72855d8928c07ff4a166759546ed23cushon    for (Type.ClassTy.SimpleClassTy c : ty.classes) {
64d1a195115e72855d8928c07ff4a166759546ed23cushon      if (c.targs().isEmpty()) {
65d1a195115e72855d8928c07ff4a166759546ed23cushon        classes.add(c);
66d1a195115e72855d8928c07ff4a166759546ed23cushon      } else {
677e2d4aea15dacf4732174504a7a08f9c6ae1ffb3cushon        classes.add(new Type.ClassTy.SimpleClassTy(c.sym(), ImmutableList.of(), c.annos()));
68d1a195115e72855d8928c07ff4a166759546ed23cushon      }
69d1a195115e72855d8928c07ff4a166759546ed23cushon    }
70d1a195115e72855d8928c07ff4a166759546ed23cushon    return new Type.ClassTy(classes.build());
71d1a195115e72855d8928c07ff4a166759546ed23cushon  }
72d1a195115e72855d8928c07ff4a166759546ed23cushon}
73