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
17package com.google.turbine.bytecode.sig;
18
19import com.google.common.collect.ImmutableList;
20import com.google.turbine.model.TurbineConstantTypeKind;
21import javax.annotation.Nullable;
22
23/** JVMS 4.7.9.1 signatures. */
24public class Sig {
25
26  /** A JVMS 4.7.9.1 ClassSignature. */
27  public static class ClassSig {
28
29    private final ImmutableList<TyParamSig> tyParams;
30    private final ClassTySig superClass;
31    private final ImmutableList<ClassTySig> interfaces;
32
33    public ClassSig(
34        ImmutableList<TyParamSig> tyParams,
35        ClassTySig superClass,
36        ImmutableList<ClassTySig> interfaces) {
37      this.tyParams = tyParams;
38      this.superClass = superClass;
39      this.interfaces = interfaces;
40    }
41
42    /** Formal type parameters. */
43    public ImmutableList<TyParamSig> tyParams() {
44      return tyParams;
45    }
46
47    /** The super class. */
48    public ClassTySig superClass() {
49      return superClass;
50    }
51
52    /** The interface list. */
53    public ImmutableList<ClassTySig> interfaces() {
54      return interfaces;
55    }
56  }
57
58  /** A JVMS 4.7.9.1 FormalTypeParameter. */
59  public static class TyParamSig {
60
61    private final String name;
62    @Nullable private final TySig classBound;
63    private final ImmutableList<TySig> interfaceBounds;
64
65    public TyParamSig(String name, TySig classBound, ImmutableList<TySig> interfaceBounds) {
66      this.name = name;
67      this.classBound = classBound;
68      this.interfaceBounds = interfaceBounds;
69    }
70
71    /** A single class upper-bound, or {@code null}. */
72    @Nullable
73    public TySig classBound() {
74      return classBound;
75    }
76
77    /** Interface upper-bounds. */
78    public ImmutableList<TySig> interfaceBounds() {
79      return interfaceBounds;
80    }
81
82    /** The name of the type parameter. */
83    public String name() {
84      return name;
85    }
86  }
87
88  /** A JVMS 4.7.9.1 ClassTypeSignature. */
89  public static class ClassTySig extends TySig {
90
91    private final String pkg;
92    private final ImmutableList<SimpleClassTySig> classes;
93
94    public ClassTySig(String pkg, ImmutableList<SimpleClassTySig> classes) {
95      this.pkg = pkg;
96      this.classes = classes;
97    }
98
99    /** The package name of the class. */
100    public String pkg() {
101      return pkg;
102    }
103
104    /**
105     * A list of a simple names, containing at least one top-level type and possible repeated member
106     * class names. Each element may include type arguments.
107     *
108     * <p>It's possible for the top-level type to be a desugared nested class with no type
109     * arguments, in this case the first element is the simple name of the lowered type, e.g. in
110     * {@code Foo$Bar<X>.<Y>} the first element may be an nested class {@code Bar} with an enclosing
111     * type {@code Foo}, but it may also be a top-level class that was named {@code Foo$Bar} in
112     * source. The signature is the same either way.
113     */
114    public ImmutableList<SimpleClassTySig> classes() {
115      return classes;
116    }
117
118    @Override
119    public TySigKind kind() {
120      return TySigKind.CLASS_TY_SIG;
121    }
122  }
123
124  /** A JVMS 4.7.9.1 SimpleClassTypeSignature. */
125  public static class SimpleClassTySig {
126
127    private final String simpleName;
128    private final ImmutableList<TySig> tyArgs;
129
130    public SimpleClassTySig(String simpleName, ImmutableList<TySig> tyArgs) {
131      this.tyArgs = tyArgs;
132      this.simpleName = simpleName;
133    }
134
135    /** Type arguments. */
136    public ImmutableList<TySig> tyArgs() {
137      return tyArgs;
138    }
139
140    /** The simple name of the class. */
141    public String simpleName() {
142      return simpleName;
143    }
144  }
145
146  /**
147   * A wildcard type.
148   *
149   * <p>Wildcard are represented as first class types, instead only allowing them as top-level type
150   * arguments. This diverges from the buggy grammar in JVMS 4.7.9.1, see:
151   * http://mail.openjdk.java.net/pipermail/compiler-dev/2016-October/010450.html
152   */
153  public abstract static class WildTySig extends TySig {
154    /** A wildcard bound kind. */
155    public enum BoundKind {
156      /** An unbounded wildcard. */
157      NONE,
158      /** A lower-bounded wildcard. */
159      LOWER,
160      /** An upper-bounded wildcard. */
161      UPPER
162    }
163
164    /** Returns the wildcard bound kind. */
165    public abstract BoundKind boundKind();
166
167    @Override
168    public TySigKind kind() {
169      return TySigKind.WILD_TY_SIG;
170    }
171  }
172
173  /** An upper-bounded wildcard. */
174  public static class UpperBoundTySig extends WildTySig {
175
176    private final TySig bound;
177
178    public UpperBoundTySig(TySig bound) {
179      this.bound = bound;
180    }
181
182    /** The upper bound. */
183    public TySig bound() {
184      return bound;
185    }
186
187    @Override
188    public BoundKind boundKind() {
189      return BoundKind.UPPER;
190    }
191  }
192
193  /** An lower-bounded wildcard. */
194  public static class LowerBoundTySig extends WildTySig {
195
196    private final TySig bound;
197
198    public LowerBoundTySig(TySig bound) {
199      this.bound = bound;
200    }
201
202    /** The lower bound. */
203    public TySig bound() {
204      return bound;
205    }
206
207    @Override
208    public BoundKind boundKind() {
209      return BoundKind.LOWER;
210    }
211  }
212
213  /** An unbounded wildcard. */
214  public static class WildTyArgSig extends WildTySig {
215    @Override
216    public BoundKind boundKind() {
217      return BoundKind.NONE;
218    }
219  }
220
221  /** A JVMS 4.7.9.1 ArrayTypeSignature. */
222  public static class ArrayTySig extends TySig {
223
224    private final TySig elementType;
225
226    public ArrayTySig(TySig elementType) {
227      this.elementType = elementType;
228    }
229
230    /** The element type. */
231    public TySig elementType() {
232      return elementType;
233    }
234
235    @Override
236    public TySigKind kind() {
237      return TySigKind.ARRAY_TY_SIG;
238    }
239  }
240
241  /** A JVMS 4.7.9.1 TypeVariableSignature. */
242  public static class TyVarSig extends TySig {
243
244    public final String name;
245
246    public TyVarSig(String name) {
247      this.name = name;
248    }
249
250    /** The name of the type variable. */
251    public String name() {
252      return name;
253    }
254
255    @Override
256    public TySigKind kind() {
257      return TySigKind.TY_VAR_SIG;
258    }
259  }
260
261  /** An abstract class for all JVMS 4.7.9.1 JavaTypeSignatures. */
262  public abstract static class TySig {
263
264    /** The type kind. */
265    public enum TySigKind {
266      VOID_TY_SIG,
267      BASE_TY_SIG,
268      CLASS_TY_SIG,
269      ARRAY_TY_SIG,
270      TY_VAR_SIG,
271      WILD_TY_SIG
272    }
273
274    /** The type kind. */
275    public abstract TySigKind kind();
276  }
277
278  /** A JVMS 4.3.3 VoidDescriptor. */
279  public static final TySig VOID =
280      new TySig() {
281        @Override
282        public TySigKind kind() {
283          return TySigKind.VOID_TY_SIG;
284        }
285      };
286
287  /** A JVMS 4.3.2 BaseType. */
288  public static class BaseTySig extends TySig {
289
290    @Override
291    public TySigKind kind() {
292      return TySigKind.BASE_TY_SIG;
293    }
294
295    private final TurbineConstantTypeKind type;
296
297    public BaseTySig(TurbineConstantTypeKind type) {
298      this.type = type;
299    }
300
301    /** The base type kind. */
302    public TurbineConstantTypeKind type() {
303      return type;
304    }
305  }
306
307  /** A JVMS 4.7.9.1 MethodTypeSignature. */
308  public static class MethodSig {
309
310    private final ImmutableList<TyParamSig> tyParams;
311    private final ImmutableList<TySig> params;
312    private final TySig returnType;
313    private final ImmutableList<TySig> exceptions;
314
315    public MethodSig(
316        ImmutableList<TyParamSig> tyParams,
317        ImmutableList<TySig> params,
318        TySig returnType,
319        ImmutableList<TySig> exceptions) {
320      this.tyParams = tyParams;
321      this.params = params;
322      this.returnType = returnType;
323      this.exceptions = exceptions;
324    }
325
326    /** The formal type parameters. */
327    public ImmutableList<TyParamSig> tyParams() {
328      return tyParams;
329    }
330
331    /** The return type. Non-null, possibly {@link #VOID}. */
332    public TySig returnType() {
333      return returnType;
334    }
335
336    /** The formal parameters. */
337    public ImmutableList<TySig> params() {
338      return params;
339    }
340
341    /** The thrown exceptions. */
342    public ImmutableList<TySig> exceptions() {
343      return exceptions;
344    }
345  }
346}
347