|
1 |
| package edu.rice.cs.dynamicjava.symbol; |
|
2 |
| |
|
3 |
| import java.util.*; |
|
4 |
| |
|
5 |
| import edu.rice.cs.plt.tuple.Pair; |
|
6 |
| import edu.rice.cs.plt.tuple.Option; |
|
7 |
| import edu.rice.cs.plt.tuple.Wrapper; |
|
8 |
| import edu.rice.cs.plt.recur.*; |
|
9 |
| import edu.rice.cs.plt.lambda.*; |
|
10 |
| import edu.rice.cs.plt.iter.IterUtil; |
|
11 |
| import edu.rice.cs.plt.collect.CollectUtil; |
|
12 |
| import edu.rice.cs.plt.collect.Order; |
|
13 |
| import edu.rice.cs.plt.collect.PredicateSet; |
|
14 |
| import edu.rice.cs.plt.reflect.JavaVersion; |
|
15 |
| |
|
16 |
| import koala.dynamicjava.tree.*; |
|
17 |
| import koala.dynamicjava.interpreter.TypeUtil; |
|
18 |
| import koala.dynamicjava.interpreter.NodeProperties; |
|
19 |
| import edu.rice.cs.dynamicjava.Options; |
|
20 |
| import edu.rice.cs.dynamicjava.interpreter.EvaluatorException; |
|
21 |
| import edu.rice.cs.dynamicjava.interpreter.ExpressionEvaluator; |
|
22 |
| import edu.rice.cs.dynamicjava.interpreter.RuntimeBindings; |
|
23 |
| import edu.rice.cs.dynamicjava.symbol.type.*; |
|
24 |
| |
|
25 |
| import static edu.rice.cs.plt.debug.DebugUtil.debug; |
|
26 |
| |
|
27 |
| |
|
28 |
| |
|
29 |
| |
|
30 |
| |
|
31 |
| |
|
32 |
| public abstract class StandardTypeSystem extends TypeSystem { |
|
33 |
| |
|
34 |
| private final Options _opt; |
|
35 |
| |
|
36 |
| |
|
37 |
| |
|
38 |
| |
|
39 |
| |
|
40 |
| private final boolean _boxingInMostSpecific; |
|
41 |
| |
|
42 |
| |
|
43 |
| |
|
44 |
| |
|
45 |
| |
|
46 |
| private final boolean _useExplicitTypeArgs; |
|
47 |
| |
|
48 |
| |
|
49 |
| |
|
50 |
| |
|
51 |
| |
|
52 |
| |
|
53 |
| private final boolean _strictClassEquality; |
|
54 |
| |
|
55 |
2
| protected StandardTypeSystem(Options opt, boolean boxingInMostSpecific, boolean useExplicitTypeArgs,
|
|
56 |
| boolean strictClassEquality) { |
|
57 |
2
| _opt = opt;
|
|
58 |
2
| _boxingInMostSpecific = boxingInMostSpecific;
|
|
59 |
2
| _useExplicitTypeArgs = useExplicitTypeArgs;
|
|
60 |
2
| _strictClassEquality = strictClassEquality;
|
|
61 |
| } |
|
62 |
| |
|
63 |
| |
|
64 |
| public abstract boolean isWellFormed(Type t); |
|
65 |
| |
|
66 |
| |
|
67 |
| public abstract boolean isEqual(Type t1, Type t2); |
|
68 |
| |
|
69 |
| |
|
70 |
| |
|
71 |
| |
|
72 |
| |
|
73 |
| public abstract boolean isSubtype(Type subT, Type superT); |
|
74 |
| |
|
75 |
| |
|
76 |
| public abstract Type join(Iterable<? extends Type> ts); |
|
77 |
| |
|
78 |
| |
|
79 |
| public abstract Type meet(Iterable<? extends Type> ts); |
|
80 |
| |
|
81 |
| |
|
82 |
| protected abstract Iterable<Type> captureTypeArgs(Iterable<? extends Type> targs, |
|
83 |
| Iterable<? extends VariableType> params); |
|
84 |
| |
|
85 |
| |
|
86 |
| |
|
87 |
| |
|
88 |
| |
|
89 |
| |
|
90 |
| |
|
91 |
| |
|
92 |
| |
|
93 |
| |
|
94 |
| protected abstract Iterable<Type> inferTypeArguments(Iterable<? extends VariableType> tparams, |
|
95 |
| Iterable<? extends Type> params, Type returned, |
|
96 |
| Iterable<? extends Type> args, Option<Type> expected); |
|
97 |
| |
|
98 |
| |
|
99 |
20460
| protected boolean sameClass(ClassType c1, ClassType c2) {
|
|
100 |
20460
| if (_strictClassEquality) { return c1.ofClass().equals(c2.ofClass()); }
|
|
101 |
0
| else { return c1.ofClass().fullName().equals(c2.ofClass().fullName()); }
|
|
102 |
| } |
|
103 |
| |
|
104 |
| protected static final Type CLONEABLE_AND_SERIALIZABLE = |
|
105 |
| new IntersectionType(IterUtil.make(CLONEABLE, SERIALIZABLE)); |
|
106 |
| |
|
107 |
| |
|
108 |
| private final Type ITERABLE; |
|
109 |
| { |
|
110 |
2
| Class<?> c;
|
|
111 |
2
| try { c = Class.forName("java.lang.Iterable"); }
|
|
112 |
0
| catch (ClassNotFoundException e) { c = null; }
|
|
113 |
2
| ITERABLE = (c == null) ? null : makeClassType(SymbolUtil.wrapClass(c));
|
|
114 |
| } |
|
115 |
| |
|
116 |
| |
|
117 |
| private final Type COLLECTION = makeClassType(SymbolUtil.wrapClass(Collection.class)); |
|
118 |
| |
|
119 |
| |
|
120 |
| private final Type ENUM; |
|
121 |
| { |
|
122 |
2
| Class<?> c;
|
|
123 |
2
| try { c = Class.forName("java.lang.Enum"); }
|
|
124 |
0
| catch (ClassNotFoundException e) { c = null; }
|
|
125 |
2
| ENUM = (c == null) ? null : makeClassType(SymbolUtil.wrapClass(c));
|
|
126 |
| } |
|
127 |
| |
|
128 |
| private final DJClass CLASS = SymbolUtil.wrapClass(Class.class); |
|
129 |
| |
|
130 |
41
| public TypePrinter typePrinter() { return new StandardTypePrinter(); }
|
|
131 |
| |
|
132 |
| |
|
133 |
2063
| public boolean isPrimitive(Type t) { return t.apply(IS_PRIMITIVE); }
|
|
134 |
| |
|
135 |
| protected static final TypeVisitorLambda<Boolean> IS_PRIMITIVE = new TypeAbstractVisitor<Boolean>() { |
|
136 |
244
| public Boolean defaultCase(Type t) { return false; }
|
|
137 |
1819
| @Override public Boolean forPrimitiveType(PrimitiveType t) { return true; }
|
|
138 |
| }; |
|
139 |
| |
|
140 |
| |
|
141 |
1518
| public boolean isReference(Type t) { return t.apply(IS_REFERENCE); }
|
|
142 |
| |
|
143 |
| protected static final TypeVisitorLambda<Boolean> IS_REFERENCE = new TypeAbstractVisitor<Boolean>() { |
|
144 |
88
| public Boolean defaultCase(Type t) { return false; }
|
|
145 |
1409
| @Override public Boolean forReferenceType(ReferenceType t) { return true; }
|
|
146 |
21
| @Override public Boolean forVariableType(VariableType t) { return true; }
|
|
147 |
0
| @Override public Boolean forIntersectionType(IntersectionType t) { return true; }
|
|
148 |
0
| @Override public Boolean forUnionType(UnionType t) { return true; }
|
|
149 |
| }; |
|
150 |
| |
|
151 |
| |
|
152 |
127
| public boolean isArray(Type t) { return t.apply(IS_ARRAY); }
|
|
153 |
| |
|
154 |
| protected static final TypeVisitorLambda<Boolean> IS_ARRAY = new TypeAbstractVisitor<Boolean>() { |
|
155 |
| private final Predicate<Type> PRED = LambdaUtil.asPredicate(this); |
|
156 |
3
| public Boolean defaultCase(Type t) { return false; }
|
|
157 |
124
| @Override public Boolean forArrayType(ArrayType t) { return true; }
|
|
158 |
0
| @Override public Boolean forVariableType(VariableType t) { return t.symbol().upperBound().apply(this); }
|
|
159 |
0
| @Override public Boolean forIntersectionType(IntersectionType t) { return IterUtil.or(t.ofTypes(), PRED); }
|
|
160 |
0
| @Override public Boolean forUnionType(UnionType t) {
|
|
161 |
| |
|
162 |
0
| return !IterUtil.isEmpty(t.ofTypes()) && IterUtil.and(t.ofTypes(), PRED);
|
|
163 |
| } |
|
164 |
| }; |
|
165 |
| |
|
166 |
| |
|
167 |
| |
|
168 |
| |
|
169 |
| |
|
170 |
3
| public boolean isIterable(Type t) { return isSubtype(t, ITERABLE == null ? COLLECTION : ITERABLE); }
|
|
171 |
| |
|
172 |
| |
|
173 |
| |
|
174 |
| |
|
175 |
| |
|
176 |
| |
|
177 |
0
| public boolean isEnum(Type t) { return ENUM != null && isSubtype(t, ENUM); }
|
|
178 |
| |
|
179 |
| |
|
180 |
12
| public boolean isReifiable(Type t) { return t.apply(IS_REIFIABLE); }
|
|
181 |
| |
|
182 |
| |
|
183 |
| private final TypeVisitorLambda<Boolean> IS_REIFIABLE = new TypeAbstractVisitor<Boolean>() { |
|
184 |
| |
|
185 |
0
| public Boolean defaultCase(Type t) { return false; }
|
|
186 |
5
| @Override public Boolean forPrimitiveType(PrimitiveType t) { return true; }
|
|
187 |
0
| @Override public Boolean forNullType(NullType t) { return true; }
|
|
188 |
0
| @Override public Boolean forArrayType(ArrayType t) { return t.ofType().apply(this); }
|
|
189 |
7
| @Override public Boolean forSimpleClassType(SimpleClassType t) { return true; }
|
|
190 |
0
| @Override public Boolean forRawClassType(RawClassType t) { return true; }
|
|
191 |
0
| @Override public Boolean forVoidType(VoidType t) { return true; }
|
|
192 |
| |
|
193 |
0
| @Override public Boolean forParameterizedClassType (ParameterizedClassType t) {
|
|
194 |
0
| for (Type targ : t.typeArguments()) {
|
|
195 |
0
| if (!targ.apply(IS_UNBOUNDED_WILDCARD)) { return false; }
|
|
196 |
| } |
|
197 |
0
| return true;
|
|
198 |
| } |
|
199 |
| }; |
|
200 |
| |
|
201 |
| |
|
202 |
| private final TypeVisitorLambda<Boolean> IS_UNBOUNDED_WILDCARD = new TypeAbstractVisitor<Boolean>() { |
|
203 |
0
| public Boolean defaultCase(Type t) { return false; }
|
|
204 |
0
| @Override public Boolean forWildcard(Wildcard t) {
|
|
205 |
0
| return isEqual(t.symbol().upperBound(), OBJECT) && isEqual(t.symbol().lowerBound(), NULL);
|
|
206 |
| } |
|
207 |
| }; |
|
208 |
| |
|
209 |
| |
|
210 |
| |
|
211 |
| |
|
212 |
| |
|
213 |
483
| public boolean isConcrete(Type t) { return t.apply(IS_CONCRETE); }
|
|
214 |
| |
|
215 |
| private static final TypeVisitorLambda<Boolean> IS_CONCRETE = new TypeAbstractVisitor<Boolean>() { |
|
216 |
0
| public Boolean defaultCase(Type t) { return false; }
|
|
217 |
0
| @Override public Boolean forPrimitiveType(PrimitiveType t) { return true; }
|
|
218 |
0
| @Override public Boolean forArrayType(ArrayType t) { return true; }
|
|
219 |
316
| @Override public Boolean forSimpleClassType(SimpleClassType t) { return isConcreteClass(t.ofClass()); }
|
|
220 |
0
| @Override public Boolean forRawClassType(RawClassType t) { return isConcreteClass(t.ofClass()); }
|
|
221 |
| |
|
222 |
167
| @Override public Boolean forParameterizedClassType(ParameterizedClassType t) {
|
|
223 |
0
| if (!isConcreteClass(t.ofClass())) { return false; }
|
|
224 |
167
| for (Type targ : t.typeArguments()) {
|
|
225 |
0
| if (targ instanceof Wildcard) { return false; }
|
|
226 |
| } |
|
227 |
167
| return true;
|
|
228 |
| } |
|
229 |
| |
|
230 |
483
| private boolean isConcreteClass(DJClass c) {
|
|
231 |
483
| return !c.isInterface() && !c.isAbstract();
|
|
232 |
| } |
|
233 |
| }; |
|
234 |
| |
|
235 |
483
| public Option<Type> dynamicallyEnclosingType(Type t) { return t.apply(DYNAMICALLY_ENCLOSING); }
|
|
236 |
| |
|
237 |
| private static final TypeVisitorLambda<Option<Type>> DYNAMICALLY_ENCLOSING = |
|
238 |
| new TypeAbstractVisitor<Option<Type>>() { |
|
239 |
0
| public Option<Type> defaultCase(Type t) { return Option.none(); }
|
|
240 |
| |
|
241 |
483
| @Override public Option<Type> forClassType(ClassType t) {
|
|
242 |
483
| return Option.<Type>wrap(SymbolUtil.dynamicOuterClassType(t));
|
|
243 |
| } |
|
244 |
| }; |
|
245 |
| |
|
246 |
| |
|
247 |
0
| public boolean isExtendable(Type t) { return t.apply(IS_EXTENDABLE); }
|
|
248 |
| |
|
249 |
| private static final TypeVisitorLambda<Boolean> IS_EXTENDABLE = new TypeAbstractVisitor<Boolean>() { |
|
250 |
0
| public Boolean defaultCase(Type t) { return false; }
|
|
251 |
| |
|
252 |
0
| @Override public Boolean forClassType(ClassType t) {
|
|
253 |
0
| return !t.ofClass().isInterface() && !t.ofClass().isFinal();
|
|
254 |
| } |
|
255 |
| }; |
|
256 |
| |
|
257 |
| |
|
258 |
| |
|
259 |
0
| public boolean isImplementable(Type t) { return t.apply(IS_IMPLEMENTABLE); }
|
|
260 |
| |
|
261 |
| private static final TypeVisitorLambda<Boolean> IS_IMPLEMENTABLE = new TypeAbstractVisitor<Boolean>() { |
|
262 |
0
| public Boolean defaultCase(Type t) { return false; }
|
|
263 |
0
| @Override public Boolean forClassType(ClassType t) { return t.ofClass().isInterface(); }
|
|
264 |
| }; |
|
265 |
| |
|
266 |
| |
|
267 |
| |
|
268 |
14
| protected boolean containsVar(Type t, final VariableType var) {
|
|
269 |
14
| return containsAnyVar(t, Collections.singleton(var));
|
|
270 |
| } |
|
271 |
| |
|
272 |
| |
|
273 |
14
| protected boolean containsAnyVar(Type t, final Set<? extends VariableType> vars) {
|
|
274 |
14
| return t.apply(new TypeAbstractVisitor<Boolean>() {
|
|
275 |
| private final RecursionStack<Type> _stack = new RecursionStack<Type>(Wrapper.<Type>factory()); |
|
276 |
0
| public Boolean defaultCase(Type t) { return false; }
|
|
277 |
0
| @Override public Boolean forArrayType(ArrayType t) { return t.ofType().apply(this); }
|
|
278 |
0
| @Override public Boolean forParameterizedClassType(ParameterizedClassType t) {
|
|
279 |
0
| return checkList(t.typeArguments());
|
|
280 |
| } |
|
281 |
0
| @Override public Boolean forBoundType(BoundType t) { return checkList(t.ofTypes()); }
|
|
282 |
14
| @Override public Boolean forVariableType(VariableType t) {
|
|
283 |
14
| return vars.contains(t) || checkBoundedSymbol(t, t.symbol());
|
|
284 |
| } |
|
285 |
0
| @Override public Boolean forWildcard(Wildcard w) { return checkBoundedSymbol(w, w.symbol()); }
|
|
286 |
| |
|
287 |
0
| private Boolean checkList(Iterable<? extends Type> types) {
|
|
288 |
0
| for (Type t : types) {
|
|
289 |
0
| if (t.apply(this)) { return true; }
|
|
290 |
| } |
|
291 |
0
| return false;
|
|
292 |
| } |
|
293 |
| |
|
294 |
0
| private Boolean checkBoundedSymbol(Type t, final BoundedSymbol s) {
|
|
295 |
0
| final TypeVisitor<Boolean> visitor = this;
|
|
296 |
0
| Thunk<Boolean> handleBounds = new Thunk<Boolean>() {
|
|
297 |
0
| public Boolean value() {
|
|
298 |
0
| return s.lowerBound().apply(visitor) || s.upperBound().apply(visitor);
|
|
299 |
| } |
|
300 |
| }; |
|
301 |
0
| return _stack.apply(handleBounds, false, t);
|
|
302 |
| } |
|
303 |
| |
|
304 |
| }); |
|
305 |
| } |
|
306 |
| |
|
307 |
| |
|
308 |
| |
|
309 |
0
| public boolean isDisjoint(final Type s, final Type t) {
|
|
310 |
| |
|
311 |
| abstract class Visitor extends TypeAbstractVisitor<Boolean> { |
|
312 |
| private final Type _other; |
|
313 |
0
| public Visitor(Type other) { _other = other; }
|
|
314 |
| public abstract boolean recur(Type that); |
|
315 |
0
| @Override public Boolean forPrimitiveType(PrimitiveType that) {
|
|
316 |
0
| return !isSubtype(that, _other) && !isSubtype(_other, that);
|
|
317 |
| } |
|
318 |
0
| @Override public Boolean forNullType(NullType that) {
|
|
319 |
0
| return !isSubtype(that, _other);
|
|
320 |
| } |
|
321 |
0
| @Override public Boolean forArrayType(ArrayType that) { return null; }
|
|
322 |
0
| @Override public Boolean forClassType(ClassType that) { return null; }
|
|
323 |
0
| @Override public Boolean forIntersectionType(IntersectionType that) {
|
|
324 |
0
| for (Type elt : that.ofTypes()) { if (recur(elt)) return true; }
|
|
325 |
0
| return false;
|
|
326 |
| } |
|
327 |
0
| @Override public Boolean forUnionType(UnionType that) {
|
|
328 |
0
| for (Type elt : that.ofTypes()) { if (!recur(elt)) return false; }
|
|
329 |
0
| return true;
|
|
330 |
| } |
|
331 |
0
| @Override public Boolean forVariableType(VariableType that) {
|
|
332 |
| |
|
333 |
0
| return false;
|
|
334 |
| } |
|
335 |
0
| @Override public Boolean forTopType(TopType s) { return false; }
|
|
336 |
0
| @Override public Boolean forBottomType(BottomType s) { return true; }
|
|
337 |
| } |
|
338 |
| |
|
339 |
0
| Boolean sResult = s.apply(new Visitor(t) {
|
|
340 |
0
| public boolean recur(Type that) { return isDisjoint(that, t); }
|
|
341 |
| }); |
|
342 |
0
| if (sResult != null) { return sResult; }
|
|
343 |
| else { |
|
344 |
0
| return t.apply(new Visitor(s) {
|
|
345 |
0
| public boolean recur(Type that) { return isDisjoint(s, that); }
|
|
346 |
0
| @Override public Boolean forArrayType(ArrayType t) {
|
|
347 |
0
| if (s instanceof ArrayType) { return isDisjoint(((ArrayType) s).ofType(), t.ofType()); }
|
|
348 |
0
| else { return !isSubtype(t, s); }
|
|
349 |
| } |
|
350 |
0
| @Override public Boolean forClassType(ClassType t) {
|
|
351 |
0
| if (s instanceof ArrayType) { return !isSubtype(s, t); }
|
|
352 |
| else { |
|
353 |
0
| ClassType sAsClass = (ClassType) s;
|
|
354 |
0
| if (sAsClass.ofClass().isFinal() || t.ofClass().isFinal() ||
|
|
355 |
| (!sAsClass.ofClass().isInterface() && !t.ofClass().isInterface())) { |
|
356 |
| |
|
357 |
0
| if (!isSubtype(s, erase(t)) && !isSubtype(t, erase(s))) { return true; }
|
|
358 |
| } |
|
359 |
| |
|
360 |
0
| return false;
|
|
361 |
| } |
|
362 |
| } |
|
363 |
| }); |
|
364 |
| } |
|
365 |
| } |
|
366 |
| |
|
367 |
| |
|
368 |
373
| public boolean isAssignable(Type target, Type expT) {
|
|
369 |
| |
|
370 |
373
| try {
|
|
371 |
373
| Expression e = TypeUtil.makeEmptyExpression();
|
|
372 |
373
| NodeProperties.setType(e, expT);
|
|
373 |
373
| assign(target, e);
|
|
374 |
190
| return true;
|
|
375 |
| } |
|
376 |
183
| catch (UnsupportedConversionException e) { return false; }
|
|
377 |
| } |
|
378 |
| |
|
379 |
| |
|
380 |
0
| public boolean isAssignable(Type target, Type expT, Object expValue) {
|
|
381 |
| |
|
382 |
0
| try {
|
|
383 |
0
| Expression e = TypeUtil.makeEmptyExpression();
|
|
384 |
0
| NodeProperties.setType(e, expT);
|
|
385 |
0
| NodeProperties.setValue(e, expValue);
|
|
386 |
0
| assign(target, e);
|
|
387 |
0
| return true;
|
|
388 |
| } |
|
389 |
0
| catch (UnsupportedConversionException e) { return false; }
|
|
390 |
| } |
|
391 |
| |
|
392 |
16
| public boolean isPrimitiveConvertible(Type t) {
|
|
393 |
16
| return isPrimitive(t) ||
|
|
394 |
| (!_opt.prohibitBoxing() && !isSubtype(t, NULL) && |
|
395 |
| (isSubtype(t, BOOLEAN_CLASS) || |
|
396 |
| isSubtype(t, CHARACTER_CLASS) || |
|
397 |
| isSubtype(t, BYTE_CLASS) || |
|
398 |
| isSubtype(t, SHORT_CLASS) || |
|
399 |
| isSubtype(t, INTEGER_CLASS) || |
|
400 |
| isSubtype(t, LONG_CLASS) || |
|
401 |
| isSubtype(t, FLOAT_CLASS) || |
|
402 |
| isSubtype(t, DOUBLE_CLASS))); |
|
403 |
| } |
|
404 |
| |
|
405 |
| |
|
406 |
55
| public boolean isReferenceConvertible(Type t) {
|
|
407 |
55
| return isReference(t) || !_opt.prohibitBoxing() && t instanceof PrimitiveType;
|
|
408 |
| } |
|
409 |
| |
|
410 |
| |
|
411 |
0
| public Type immediateSuperclass(Type t) {
|
|
412 |
0
| if (t instanceof ClassType) { return ((ClassType) t).ofClass().immediateSuperclass(); }
|
|
413 |
0
| else { return null; }
|
|
414 |
| } |
|
415 |
| |
|
416 |
2137
| public Type capture(Type t) { return t.apply(CAPTURE); }
|
|
417 |
| |
|
418 |
| |
|
419 |
| private final TypeVisitorLambda<Type> CAPTURE = new TypeAbstractVisitor<Type>() { |
|
420 |
1793
| public Type defaultCase(Type t) { return t; }
|
|
421 |
144
| public Type forVarargArrayType(VarargArrayType t) { return new SimpleArrayType(t.ofType()); }
|
|
422 |
200
| @Override public Type forParameterizedClassType(ParameterizedClassType t) { return capture(t); }
|
|
423 |
| }; |
|
424 |
| |
|
425 |
3402
| protected ParameterizedClassType capture(ParameterizedClassType t) {
|
|
426 |
3402
| boolean ground = true;
|
|
427 |
3402
| for (Type arg : t.typeArguments()) {
|
|
428 |
284
| if (arg instanceof Wildcard) { ground = false; break; }
|
|
429 |
| } |
|
430 |
3118
| if (ground) { return t; }
|
|
431 |
| else { |
|
432 |
284
| Iterable<VariableType> params = SymbolUtil.allTypeParameters(t.ofClass());
|
|
433 |
284
| Iterable<Type> captureArgs = captureTypeArgs(t.typeArguments(), params);
|
|
434 |
284
| return new ParameterizedClassType(t.ofClass(), captureArgs);
|
|
435 |
| } |
|
436 |
| } |
|
437 |
| |
|
438 |
| |
|
439 |
| |
|
440 |
| |
|
441 |
| |
|
442 |
5187
| public Type erase(Type t) { return t.apply(ERASE); }
|
|
443 |
| |
|
444 |
| private static final TypeVisitorLambda<Type> ERASE = new TypeAbstractVisitor<Type>() { |
|
445 |
1852
| public Type defaultCase(Type t) { return t; }
|
|
446 |
| |
|
447 |
0
| @Override public Type forNullType(NullType t) { return OBJECT; }
|
|
448 |
| |
|
449 |
28
| @Override public Type forSimpleArrayType(SimpleArrayType t) {
|
|
450 |
28
| Type newElementType = t.ofType().apply(this);
|
|
451 |
28
| return (t.ofType() == newElementType) ? t : new SimpleArrayType(newElementType);
|
|
452 |
| } |
|
453 |
| |
|
454 |
56
| @Override public Type forVarargArrayType(VarargArrayType t) {
|
|
455 |
56
| Type newElementType = t.ofType().apply(this);
|
|
456 |
56
| return (t.ofType() == newElementType) ? t : new VarargArrayType(newElementType);
|
|
457 |
| } |
|
458 |
| |
|
459 |
8300
| @Override public Type forParameterizedClassType(ParameterizedClassType t) {
|
|
460 |
8300
| return new RawClassType(t.ofClass());
|
|
461 |
| } |
|
462 |
| |
|
463 |
255
| @Override public Type forVariableType(VariableType t) { return t.symbol().upperBound().apply(this); }
|
|
464 |
| |
|
465 |
0
| @Override public Type forIntersectionType(IntersectionType t) {
|
|
466 |
0
| if (IterUtil.isEmpty(t.ofTypes())) { return OBJECT; }
|
|
467 |
0
| else { return IterUtil.first(t.ofTypes()).apply(this); }
|
|
468 |
| } |
|
469 |
| |
|
470 |
8
| @Override public Type forUnionType(UnionType t) {
|
|
471 |
| |
|
472 |
8
| return OBJECT;
|
|
473 |
| } |
|
474 |
| |
|
475 |
0
| @Override public Type forWildcard(Wildcard t) { throw new IllegalArgumentException(); }
|
|
476 |
0
| @Override public Type forTopType(TopType t) { throw new IllegalArgumentException(); }
|
|
477 |
0
| @Override public Type forBottomType(BottomType t) { throw new IllegalArgumentException(); }
|
|
478 |
| }; |
|
479 |
| |
|
480 |
| |
|
481 |
| |
|
482 |
| |
|
483 |
| |
|
484 |
| |
|
485 |
| |
|
486 |
1234
| public Thunk<Class<?>> erasedClass(Type t) { return t.apply(ERASED_CLASS); }
|
|
487 |
| |
|
488 |
| private static final TypeVisitorLambda<Thunk<Class<?>>> ERASED_CLASS = new TypeVisitorLambda<Thunk<Class<?>>>() { |
|
489 |
50
| public Thunk<Class<?>> forBooleanType(BooleanType t) { return LambdaUtil.<Class<?>>valueLambda(boolean.class); }
|
|
490 |
9
| public Thunk<Class<?>> forCharType(CharType t) { return LambdaUtil.<Class<?>>valueLambda(char.class); }
|
|
491 |
14
| public Thunk<Class<?>> forByteType(ByteType t) { return LambdaUtil.<Class<?>>valueLambda(byte.class); }
|
|
492 |
14
| public Thunk<Class<?>> forShortType(ShortType t) { return LambdaUtil.<Class<?>>valueLambda(short.class); }
|
|
493 |
327
| public Thunk<Class<?>> forIntType(IntType t) { return LambdaUtil.<Class<?>>valueLambda(int.class); }
|
|
494 |
6
| public Thunk<Class<?>> forLongType(LongType t) { return LambdaUtil.<Class<?>>valueLambda(long.class); }
|
|
495 |
16
| public Thunk<Class<?>> forFloatType(FloatType t) { return LambdaUtil.<Class<?>>valueLambda(float.class); }
|
|
496 |
11
| public Thunk<Class<?>> forDoubleType(DoubleType t) { return LambdaUtil.<Class<?>>valueLambda(double.class); }
|
|
497 |
0
| public Thunk<Class<?>> forNullType(NullType t) { return forSimpleClassType(OBJECT); }
|
|
498 |
| |
|
499 |
33
| public Thunk<Class<?>> forSimpleArrayType(SimpleArrayType t) {
|
|
500 |
33
| Thunk<Class<?>> elementType = t.ofType().apply(this);
|
|
501 |
33
| return (elementType == null) ? null : SymbolUtil.arrayClassThunk(elementType);
|
|
502 |
| } |
|
503 |
| |
|
504 |
44
| public Thunk<Class<?>> forVarargArrayType(VarargArrayType t) {
|
|
505 |
44
| Thunk<Class<?>> elementType = t.ofType().apply(this);
|
|
506 |
44
| return (elementType == null) ? null : SymbolUtil.arrayClassThunk(elementType);
|
|
507 |
| } |
|
508 |
| |
|
509 |
340
| public Thunk<Class<?>> forSimpleClassType(SimpleClassType t) { return wrapDJClass(t.ofClass()); }
|
|
510 |
| |
|
511 |
1
| public Thunk<Class<?>> forRawClassType(RawClassType t) { return wrapDJClass(t.ofClass()); }
|
|
512 |
| |
|
513 |
239
| public Thunk<Class<?>> forParameterizedClassType(ParameterizedClassType t) {
|
|
514 |
239
| return wrapDJClass(t.ofClass());
|
|
515 |
| } |
|
516 |
| |
|
517 |
55
| public Thunk<Class<?>> forVariableType(VariableType t) {
|
|
518 |
55
| return t.symbol().upperBound().apply(this);
|
|
519 |
| } |
|
520 |
| |
|
521 |
0
| public Thunk<Class<?>> forIntersectionType(IntersectionType t) {
|
|
522 |
0
| Iterator<? extends Type> sups = t.ofTypes().iterator();
|
|
523 |
0
| if (!sups.hasNext()) { return null; }
|
|
524 |
0
| else { return sups.next().apply(this); }
|
|
525 |
| } |
|
526 |
| |
|
527 |
0
| public Thunk<Class<?>> forUnionType(UnionType t) { return forSimpleClassType(OBJECT); }
|
|
528 |
| |
|
529 |
0
| public Thunk<Class<?>> forWildcard(Wildcard t) { throw new IllegalArgumentException(); }
|
|
530 |
207
| public Thunk<Class<?>> forVoidType(VoidType t) { return LambdaUtil.<Class<?>>valueLambda(void.class); }
|
|
531 |
0
| public Thunk<Class<?>> forTopType(TopType t) { throw new IllegalArgumentException(); }
|
|
532 |
0
| public Thunk<Class<?>> forBottomType(BottomType t) { throw new IllegalArgumentException(); }
|
|
533 |
| |
|
534 |
580
| private Thunk<Class<?>> wrapDJClass(final DJClass c) {
|
|
535 |
580
| return new Thunk<Class<?>>() {
|
|
536 |
335
| public Class<?> value() { return c.load(); }
|
|
537 |
| }; |
|
538 |
| } |
|
539 |
| |
|
540 |
| }; |
|
541 |
| |
|
542 |
| |
|
543 |
92
| protected ParameterizedClassType parameterize(final RawClassType t) {
|
|
544 |
92
| Iterable<VariableType> tparams = SymbolUtil.allTypeParameters(t.ofClass());
|
|
545 |
92
| return new ParameterizedClassType(t.ofClass(), IterUtil.mapSnapshot(tparams, new Lambda<VariableType, Type>() {
|
|
546 |
92
| public Type value(VariableType param) {
|
|
547 |
| |
|
548 |
92
| return new Wildcard(new BoundedSymbol(Pair.make(t, param), OBJECT, NULL));
|
|
549 |
| } |
|
550 |
| })); |
|
551 |
| } |
|
552 |
| |
|
553 |
| |
|
554 |
| |
|
555 |
| |
|
556 |
| |
|
557 |
14
| public Type reflectionClassOf(Type t) {
|
|
558 |
0
| if (IterUtil.isEmpty(SymbolUtil.allTypeParameters(CLASS))) { return makeClassType(CLASS); }
|
|
559 |
| else { |
|
560 |
14
| try { return makeClassType(CLASS, IterUtil.make(t)); }
|
|
561 |
| catch (InvalidTypeArgumentException e) { |
|
562 |
0
| throw new RuntimeException("java.lang.Class has unexpected type parameter(s)");
|
|
563 |
| } |
|
564 |
| } |
|
565 |
| } |
|
566 |
| |
|
567 |
| |
|
568 |
| |
|
569 |
| |
|
570 |
| |
|
571 |
124
| public Type arrayElementType(Type t) {
|
|
572 |
124
| return t.apply(ARRAY_ELEMENT_TYPE);
|
|
573 |
| } |
|
574 |
| |
|
575 |
| |
|
576 |
| private final TypeVisitorLambda<Type> ARRAY_ELEMENT_TYPE = new TypeAbstractVisitor<Type>() { |
|
577 |
0
| public Type defaultCase(Type t) { throw new IllegalArgumentException(); }
|
|
578 |
124
| @Override public Type forArrayType(ArrayType t) { return t.ofType(); }
|
|
579 |
0
| @Override public Type forVariableType(VariableType t) { return t.symbol().upperBound().apply(this); }
|
|
580 |
0
| @Override public Type forIntersectionType(IntersectionType t) {
|
|
581 |
| |
|
582 |
0
| return meet(IterUtil.map(t.ofTypes(), new Lambda<Type, Type>() {
|
|
583 |
0
| public Type value(Type arrayT) {
|
|
584 |
0
| return arrayT.apply(IS_ARRAY) ? arrayT.apply(ARRAY_ELEMENT_TYPE) : TOP;
|
|
585 |
| } |
|
586 |
| })); |
|
587 |
| } |
|
588 |
0
| @Override public Type forUnionType(UnionType t) {
|
|
589 |
| |
|
590 |
0
| return join(IterUtil.map(t.ofTypes(), this));
|
|
591 |
| } |
|
592 |
| }; |
|
593 |
| |
|
594 |
| |
|
595 |
| protected static class SubstitutionMap { |
|
596 |
| private Map<VariableType, Type> _sigma; |
|
597 |
| private Iterable<? extends VariableType> _vars; |
|
598 |
| private Iterable<? extends Type> _values; |
|
599 |
| |
|
600 |
| public static final SubstitutionMap EMPTY = new SubstitutionMap(IterUtil.<VariableType>empty(), |
|
601 |
| EMPTY_TYPE_ITERABLE); |
|
602 |
| |
|
603 |
6029
| public SubstitutionMap(Iterable<? extends VariableType> vars, Iterable<? extends Type> values) {
|
|
604 |
6029
| _sigma = null;
|
|
605 |
6029
| _vars = vars;
|
|
606 |
6029
| _values = values;
|
|
607 |
| } |
|
608 |
| |
|
609 |
0
| public SubstitutionMap(Map<? extends VariableType, ? extends Type> map) {
|
|
610 |
| |
|
611 |
0
| _sigma = new HashMap<VariableType, Type>(map);
|
|
612 |
| } |
|
613 |
| |
|
614 |
10206
| public boolean isEmpty() {
|
|
615 |
9578
| if (_sigma == null) { return IterUtil.isEmpty(_vars); }
|
|
616 |
628
| else { return _sigma.isEmpty(); }
|
|
617 |
| } |
|
618 |
| |
|
619 |
2677
| public Type get(VariableType v) {
|
|
620 |
2470
| if (_sigma == null) { initSigma(); }
|
|
621 |
2677
| return _sigma.get(v);
|
|
622 |
| } |
|
623 |
| |
|
624 |
| |
|
625 |
2470
| private void initSigma() {
|
|
626 |
2470
| _sigma = new HashMap<VariableType, Type>();
|
|
627 |
2470
| for (Pair<VariableType, Type> pair : IterUtil.zip(_vars, _values)) {
|
|
628 |
2470
| _sigma.put(pair.first(), pair.second());
|
|
629 |
| } |
|
630 |
2470
| _vars = null;
|
|
631 |
2470
| _values = null;
|
|
632 |
| } |
|
633 |
| } |
|
634 |
| |
|
635 |
| |
|
636 |
| |
|
637 |
| |
|
638 |
| |
|
639 |
89
| protected Type substitute(Type t, Iterable<? extends VariableType> params, Iterable<? extends Type> args) {
|
|
640 |
89
| return substitute(t, new SubstitutionMap(params, args));
|
|
641 |
| } |
|
642 |
| |
|
643 |
0
| protected Type substitute(Type t, Map<? extends VariableType, ? extends Type> map) {
|
|
644 |
0
| return substitute(t, new SubstitutionMap(map));
|
|
645 |
| } |
|
646 |
| |
|
647 |
6083
| protected Type substitute(Type t, final SubstitutionMap sigma) {
|
|
648 |
267
| if (sigma.isEmpty()) { return t; }
|
|
649 |
| else { |
|
650 |
5816
| final PrecomputedRecursionStack<Type, Type> stack = PrecomputedRecursionStack.make();
|
|
651 |
| |
|
652 |
5816
| return t.apply(new TypeUpdateVisitor() {
|
|
653 |
| |
|
654 |
2677
| @Override public Type forVariableType(VariableType t) {
|
|
655 |
2677
| Type result = sigma.get(t);
|
|
656 |
2677
| return (result == null) ? t : result;
|
|
657 |
| } |
|
658 |
| |
|
659 |
20
| @Override public Type forWildcard(final Wildcard t) {
|
|
660 |
20
| final Wildcard newWildcard = new Wildcard(new BoundedSymbol(new Object()));
|
|
661 |
20
| Thunk<Type> substituteBounds = new Thunk<Type>() {
|
|
662 |
20
| public Type value() {
|
|
663 |
20
| BoundedSymbol bounds = t.symbol();
|
|
664 |
20
| Type newUpper = recur(bounds.upperBound());
|
|
665 |
20
| Type newLower = recur(bounds.lowerBound());
|
|
666 |
13
| if (newUpper == bounds.upperBound() && newLower == bounds.lowerBound()) { return t; }
|
|
667 |
| else { |
|
668 |
7
| newWildcard.symbol().initializeUpperBound(newUpper);
|
|
669 |
7
| newWildcard.symbol().initializeLowerBound(newLower);
|
|
670 |
7
| return newWildcard;
|
|
671 |
| } |
|
672 |
| } |
|
673 |
| }; |
|
674 |
20
| return stack.apply(substituteBounds, newWildcard, t);
|
|
675 |
| } |
|
676 |
| |
|
677 |
| }); |
|
678 |
| } |
|
679 |
| } |
|
680 |
| |
|
681 |
2714
| private Iterable<? extends Type> substitute(Iterable<? extends Type> ts,
|
|
682 |
| Iterable<? extends VariableType> vars, |
|
683 |
| Iterable<? extends Type> values) { |
|
684 |
2714
| return substitute(ts, new SubstitutionMap(vars, values));
|
|
685 |
| } |
|
686 |
| |
|
687 |
4123
| private Iterable<? extends Type> substitute(Iterable<? extends Type> ts, final SubstitutionMap sigma) {
|
|
688 |
1014
| if (sigma.isEmpty()) { return ts; }
|
|
689 |
| else { |
|
690 |
3109
| return IterUtil.mapSnapshot(ts, new Lambda<Type, Type>() {
|
|
691 |
3175
| public Type value(Type t) { return substitute(t, sigma); }
|
|
692 |
| }); |
|
693 |
| } |
|
694 |
| } |
|
695 |
| |
|
696 |
| |
|
697 |
| |
|
698 |
| |
|
699 |
1324
| public ClassType makeClassType(DJClass c) {
|
|
700 |
1316
| if (IterUtil.isEmpty(SymbolUtil.allTypeParameters(c))) { return new SimpleClassType(c); }
|
|
701 |
8
| else { return new RawClassType(c); }
|
|
702 |
| } |
|
703 |
| |
|
704 |
| |
|
705 |
| |
|
706 |
| |
|
707 |
| |
|
708 |
| |
|
709 |
| |
|
710 |
| |
|
711 |
| |
|
712 |
| |
|
713 |
| |
|
714 |
| |
|
715 |
521
| public ClassType makeClassType(DJClass c, Iterable<? extends Type> args) throws InvalidTypeArgumentException {
|
|
716 |
0
| if (IterUtil.isEmpty(args)) { return makeClassType(c); }
|
|
717 |
| else { |
|
718 |
521
| Iterable<VariableType> params = SymbolUtil.allTypeParameters(c);
|
|
719 |
0
| if (IterUtil.sizeOf(params) != IterUtil.sizeOf(args)) { throw new InvalidTypeArgumentException(); }
|
|
720 |
| else { |
|
721 |
521
| ParameterizedClassType result = new ParameterizedClassType(c, args);
|
|
722 |
521
| return result;
|
|
723 |
| } |
|
724 |
| } |
|
725 |
| } |
|
726 |
| |
|
727 |
| |
|
728 |
| |
|
729 |
| |
|
730 |
| |
|
731 |
| |
|
732 |
| |
|
733 |
| |
|
734 |
| |
|
735 |
| |
|
736 |
1768
| public Expression makePrimitive(Expression e) throws UnsupportedConversionException {
|
|
737 |
1768
| Type t = NodeProperties.getType(e);
|
|
738 |
1758
| if (isPrimitive(t)) { return e; }
|
|
739 |
0
| else if (_opt.prohibitBoxing()) { throw new UnsupportedConversionException(); }
|
|
740 |
| |
|
741 |
| |
|
742 |
| |
|
743 |
1
| else if (isSubtype(t, NULL)) { throw new UnsupportedConversionException(); }
|
|
744 |
1
| else if (isSubtype(t, BOOLEAN_CLASS)) { return unbox(e, "booleanValue"); }
|
|
745 |
1
| else if (isSubtype(t, CHARACTER_CLASS)) { return unbox(e, "charValue"); }
|
|
746 |
1
| else if (isSubtype(t, BYTE_CLASS)) { return unbox(e, "byteValue"); }
|
|
747 |
1
| else if (isSubtype(t, SHORT_CLASS)) { return unbox(e, "shortValue"); }
|
|
748 |
1
| else if (isSubtype(t, INTEGER_CLASS)) { return unbox(e, "intValue"); }
|
|
749 |
1
| else if (isSubtype(t, LONG_CLASS)) { return unbox(e, "longValue"); }
|
|
750 |
1
| else if (isSubtype(t, FLOAT_CLASS)) { return unbox(e, "floatValue"); }
|
|
751 |
1
| else if (isSubtype(t, DOUBLE_CLASS)) { return unbox(e, "doubleValue"); }
|
|
752 |
1
| else { throw new UnsupportedConversionException(); }
|
|
753 |
| } |
|
754 |
| |
|
755 |
8
| private Expression unbox(Expression exp, String methodName) {
|
|
756 |
8
| ObjectMethodCall result = new ObjectMethodCall(exp, methodName, null, exp.getSourceInfo());
|
|
757 |
8
| try {
|
|
758 |
8
| ObjectMethodInvocation inv = lookupMethod(exp, methodName, EMPTY_TYPE_ITERABLE, EMPTY_EXPRESSION_ITERABLE,
|
|
759 |
| NONE_TYPE_OPTION, new TopLevelAccessModule("")); |
|
760 |
8
| result.setExpression(inv.object());
|
|
761 |
8
| result.setArguments(CollectUtil.makeList(inv.args()));
|
|
762 |
8
| NodeProperties.setMethod(result, inv.method());
|
|
763 |
8
| NodeProperties.setType(result, capture(inv.returnType()));
|
|
764 |
0
| if (NodeProperties.hasValue(exp)) { NodeProperties.setValue(result, NodeProperties.getValue(exp)); }
|
|
765 |
8
| return result;
|
|
766 |
| } |
|
767 |
0
| catch (TypeSystemException e) { throw new RuntimeException("Unboxing method inaccessible", e); }
|
|
768 |
| } |
|
769 |
| |
|
770 |
| |
|
771 |
| |
|
772 |
| |
|
773 |
| |
|
774 |
| |
|
775 |
| |
|
776 |
| |
|
777 |
| |
|
778 |
190
| public Expression makeReference(final Expression e) throws UnsupportedConversionException {
|
|
779 |
190
| Type t = NodeProperties.getType(e);
|
|
780 |
172
| if (isReference(t)) { return e; }
|
|
781 |
0
| else if (_opt.prohibitBoxing()) { throw new UnsupportedConversionException(); }
|
|
782 |
| else { |
|
783 |
18
| Expression result = t.apply(new TypeAbstractVisitor<Expression>() {
|
|
784 |
0
| public Expression defaultCase(Type t) { return null; }
|
|
785 |
2
| @Override public Expression forBooleanType(BooleanType t) { return box(e, BOOLEAN_CLASS); }
|
|
786 |
2
| @Override public Expression forCharType(CharType t) { return box(e, CHARACTER_CLASS); }
|
|
787 |
2
| @Override public Expression forByteType(ByteType t) { return box(e, BYTE_CLASS); }
|
|
788 |
2
| @Override public Expression forShortType(ShortType t) { return box(e, SHORT_CLASS); }
|
|
789 |
5
| @Override public Expression forIntType(IntType t) { return box(e, INTEGER_CLASS); }
|
|
790 |
2
| @Override public Expression forLongType(LongType t) { return box(e, LONG_CLASS); }
|
|
791 |
1
| @Override public Expression forFloatType(FloatType t) { return box(e, FLOAT_CLASS); }
|
|
792 |
2
| @Override public Expression forDoubleType(DoubleType t) { return box(e, DOUBLE_CLASS); }
|
|
793 |
| }); |
|
794 |
0
| if (result == null) { throw new UnsupportedConversionException(); }
|
|
795 |
18
| else { return result; }
|
|
796 |
| } |
|
797 |
| } |
|
798 |
| |
|
799 |
18
| private Expression box(Expression exp, ClassType boxedType) {
|
|
800 |
18
| ReferenceTypeName boxedTypeName = new ReferenceTypeName("java", "lang", boxedType.ofClass().declaredName());
|
|
801 |
18
| NodeProperties.setType(boxedTypeName, boxedType);
|
|
802 |
18
| List<Expression> arguments = Collections.singletonList(exp);
|
|
803 |
18
| if (JavaVersion.CURRENT.supports(JavaVersion.JAVA_5)) {
|
|
804 |
18
| StaticMethodCall m = new StaticMethodCall(boxedTypeName, "valueOf", arguments, exp.getSourceInfo());
|
|
805 |
18
| try {
|
|
806 |
18
| MethodInvocation inv = lookupStaticMethod(boxedType, "valueOf", EMPTY_TYPE_ITERABLE, arguments,
|
|
807 |
| NONE_TYPE_OPTION, new TopLevelAccessModule("")); |
|
808 |
18
| m.setArguments(CollectUtil.makeList(inv.args()));
|
|
809 |
18
| NodeProperties.setMethod(m, inv.method());
|
|
810 |
18
| NodeProperties.setType(m, capture(inv.returnType()));
|
|
811 |
9
| if (NodeProperties.hasValue(exp)) { NodeProperties.setValue(m, NodeProperties.getValue(exp)); }
|
|
812 |
18
| return m;
|
|
813 |
| } |
|
814 |
0
| catch (TypeSystemException e) { throw new RuntimeException("Boxing method inaccessible", e); }
|
|
815 |
| } |
|
816 |
| else { |
|
817 |
0
| SimpleAllocation k = new SimpleAllocation(boxedTypeName, arguments, exp.getSourceInfo());
|
|
818 |
0
| try {
|
|
819 |
0
| ConstructorInvocation inv = lookupConstructor(boxedType, EMPTY_TYPE_ITERABLE, arguments, NONE_TYPE_OPTION,
|
|
820 |
| new TopLevelAccessModule("")); |
|
821 |
0
| k.setArguments(CollectUtil.makeList(inv.args()));
|
|
822 |
0
| NodeProperties.setConstructor(k, inv.constructor());
|
|
823 |
0
| NodeProperties.setType(k, boxedType);
|
|
824 |
0
| if (NodeProperties.hasValue(exp)) { NodeProperties.setValue(k, NodeProperties.getValue(exp)); }
|
|
825 |
0
| return k;
|
|
826 |
| } |
|
827 |
0
| catch (TypeSystemException e) { throw new RuntimeException("Boxing constructor inaccessible", e); }
|
|
828 |
| } |
|
829 |
| } |
|
830 |
| |
|
831 |
| |
|
832 |
| |
|
833 |
| |
|
834 |
| |
|
835 |
| |
|
836 |
| |
|
837 |
| |
|
838 |
112
| public Expression unaryPromote(final Expression e) throws UnsupportedConversionException {
|
|
839 |
| |
|
840 |
112
| Expression result = NodeProperties.getType(e).apply(new TypeAbstractVisitor<Expression>() {
|
|
841 |
0
| public Expression defaultCase(Type t) { return null; }
|
|
842 |
112
| @Override public Expression forNumericType(NumericType t) { return e; }
|
|
843 |
0
| @Override public Expression forCharType(CharType t) { return makeCast(INT, e); }
|
|
844 |
0
| @Override public Expression forByteType(ByteType t) { return makeCast(INT, e); }
|
|
845 |
0
| @Override public Expression forShortType(ShortType t) { return makeCast(INT, e); }
|
|
846 |
| }); |
|
847 |
0
| if (result == null) { throw new UnsupportedConversionException(); }
|
|
848 |
112
| else { return result; }
|
|
849 |
| } |
|
850 |
| |
|
851 |
| |
|
852 |
| |
|
853 |
| |
|
854 |
| |
|
855 |
| |
|
856 |
| |
|
857 |
| |
|
858 |
| |
|
859 |
| |
|
860 |
262
| public Pair<Expression, Expression> binaryPromote(final Expression e1, final Expression e2)
|
|
861 |
| throws UnsupportedConversionException { |
|
862 |
| |
|
863 |
262
| final Type t1 = NodeProperties.getType(e1);
|
|
864 |
262
| final Type t2 = NodeProperties.getType(e2);
|
|
865 |
262
| final Type t1Promoted = t1.apply(new TypeAbstractVisitor<Type>() {
|
|
866 |
0
| @Override public Type defaultCase(Type t) { return null; }
|
|
867 |
237
| @Override public Type forNumericType(NumericType t) { return INT; }
|
|
868 |
22
| @Override public Type forFloatingPointType(FloatingPointType t) { return t; }
|
|
869 |
3
| @Override public Type forLongType(LongType t) { return t; }
|
|
870 |
| }); |
|
871 |
0
| if (t1Promoted == null) { throw new UnsupportedConversionException(); }
|
|
872 |
262
| final Type promoted = t2.apply(new TypeAbstractVisitor<Type>() {
|
|
873 |
0
| @Override public Type defaultCase(Type t) { return null; }
|
|
874 |
238
| @Override public Type forNumericType(NumericType t) { return t1Promoted; }
|
|
875 |
14
| @Override public Type forDoubleType(DoubleType t) { return t; }
|
|
876 |
8
| @Override public Type forFloatType(FloatType t) {
|
|
877 |
8
| return (t1Promoted instanceof DoubleType) ? t1Promoted : t;
|
|
878 |
| } |
|
879 |
2
| @Override public Type forLongType(LongType t) {
|
|
880 |
2
| return (t1Promoted instanceof FloatingPointType) ? t1Promoted : t;
|
|
881 |
| } |
|
882 |
| }); |
|
883 |
0
| if (promoted == null) { throw new UnsupportedConversionException(); }
|
|
884 |
| |
|
885 |
262
| return Pair.make(t1.equals(promoted) ? e1 : makeCast(promoted, e1),
|
|
886 |
262
| t2.equals(promoted) ? e2 : makeCast(promoted, e2));
|
|
887 |
| } |
|
888 |
| |
|
889 |
| |
|
890 |
| |
|
891 |
| |
|
892 |
| |
|
893 |
| |
|
894 |
| |
|
895 |
| |
|
896 |
| |
|
897 |
| |
|
898 |
0
| public Pair<Expression, Expression> mergeConditional(final Expression e1, final Expression e2)
|
|
899 |
| throws UnsupportedConversionException { |
|
900 |
0
| return NodeProperties.getType(e1).apply(new TypeAbstractVisitor<Pair<Expression, Expression>>() {
|
|
901 |
0
| public Pair<Expression, Expression> defaultCase(Type t1) {
|
|
902 |
0
| if (isNumericReference(t1)) { return checkForNumericE2(); }
|
|
903 |
0
| else if (isBooleanReference(t1) && NodeProperties.getType(e2) instanceof BooleanType) {
|
|
904 |
0
| try { return Pair.make(makePrimitive(e1), e2); }
|
|
905 |
0
| catch (UnsupportedConversionException e) { throw new RuntimeException("isBooleanReference() lied"); }
|
|
906 |
| } |
|
907 |
0
| else { return joinReferences(); }
|
|
908 |
| } |
|
909 |
| |
|
910 |
0
| @Override public Pair<Expression, Expression> forBooleanType(BooleanType t1) {
|
|
911 |
0
| Type t2 = NodeProperties.getType(e2);
|
|
912 |
0
| if (t2 instanceof BooleanType) { return Pair.make(e1, e2); }
|
|
913 |
0
| else if (isBooleanReference(t2)) {
|
|
914 |
0
| try { return Pair.make(e1, makePrimitive(e2)); }
|
|
915 |
0
| catch (UnsupportedConversionException e) { throw new RuntimeException("isBooleanReference() lied"); }
|
|
916 |
| } |
|
917 |
0
| else { return joinReferences(); }
|
|
918 |
| } |
|
919 |
| |
|
920 |
0
| @Override public Pair<Expression, Expression> forNumericType(NumericType t1) { return checkForNumericE2(); }
|
|
921 |
| |
|
922 |
0
| private boolean isNumericReference(Type t) {
|
|
923 |
0
| return !_opt.prohibitBoxing() && !isSubtype(t, NULL) &&
|
|
924 |
| (isSubtype(t, CHARACTER_CLASS) || |
|
925 |
| isSubtype(t, BYTE_CLASS) || |
|
926 |
| isSubtype(t, SHORT_CLASS) || |
|
927 |
| isSubtype(t, INTEGER_CLASS) || |
|
928 |
| isSubtype(t, LONG_CLASS) || |
|
929 |
| isSubtype(t, FLOAT_CLASS) || |
|
930 |
| isSubtype(t, DOUBLE_CLASS)); |
|
931 |
| } |
|
932 |
| |
|
933 |
0
| private boolean isBooleanReference(Type t) {
|
|
934 |
0
| return !_opt.prohibitBoxing() && isSubtype(t, BOOLEAN_CLASS) && !isSubtype(t, NULL);
|
|
935 |
| } |
|
936 |
| |
|
937 |
0
| private Pair<Expression, Expression> checkForNumericE2() {
|
|
938 |
0
| return NodeProperties.getType(e2).apply(new TypeAbstractVisitor<Pair<Expression, Expression>>() {
|
|
939 |
0
| public Pair<Expression, Expression> defaultCase(Type t2) {
|
|
940 |
0
| if (isNumericReference(t2)) { return joinNumbers(); }
|
|
941 |
0
| else { return joinReferences(); }
|
|
942 |
| } |
|
943 |
0
| @Override public Pair<Expression, Expression> forNumericType(NumericType t2) { return joinNumbers(); }
|
|
944 |
| }); |
|
945 |
| } |
|
946 |
| |
|
947 |
0
| private Pair<Expression, Expression> joinNumbers() {
|
|
948 |
0
| try {
|
|
949 |
0
| Expression unboxed1 = makePrimitive(e1);
|
|
950 |
0
| Expression unboxed2 = makePrimitive(e2);
|
|
951 |
0
| Type numT1 = NodeProperties.getType(unboxed1);
|
|
952 |
0
| Type numT2 = NodeProperties.getType(unboxed2);
|
|
953 |
0
| Type joined = null;
|
|
954 |
0
| if (NodeProperties.hasValue(unboxed1) && numT1 instanceof IntType) {
|
|
955 |
0
| joined = inRange(NodeProperties.getValue(unboxed1), numT2) ? numT2 : null;
|
|
956 |
| } |
|
957 |
0
| if (joined == null && NodeProperties.hasValue(unboxed2) && numT2 instanceof IntType) {
|
|
958 |
0
| joined = inRange(NodeProperties.getValue(unboxed2), numT1) ? numT1 : null;
|
|
959 |
| } |
|
960 |
0
| if (joined == null) { joined = join(numT1, numT2); }
|
|
961 |
0
| Expression result1 = isEqual(numT1, joined) ? unboxed1 : makeCast(joined, unboxed1);
|
|
962 |
0
| Expression result2 = isEqual(numT2, joined) ? unboxed2 : makeCast(joined, unboxed2);
|
|
963 |
0
| return Pair.make(result1, result2);
|
|
964 |
| } |
|
965 |
0
| catch (UnsupportedConversionException e) { throw new IllegalArgumentException(e); }
|
|
966 |
| } |
|
967 |
| |
|
968 |
0
| private Pair<Expression, Expression> joinReferences() {
|
|
969 |
0
| try {
|
|
970 |
0
| Expression boxed1 = makeReference(e1);
|
|
971 |
0
| Expression boxed2 = makeReference(e2);
|
|
972 |
0
| Type refT1 = NodeProperties.getType(boxed1);
|
|
973 |
0
| Type refT2 = NodeProperties.getType(boxed2);
|
|
974 |
0
| Type joined = join(refT1, refT2);
|
|
975 |
0
| Expression result1 = isEqual(refT1, joined) ? boxed1 : makeCast(joined, boxed1);
|
|
976 |
0
| Expression result2 = isEqual(refT2, joined) ? boxed2 : makeCast(joined, boxed2);
|
|
977 |
0
| return Pair.make(result1, result2);
|
|
978 |
| } |
|
979 |
0
| catch (UnsupportedConversionException e) { throw new IllegalArgumentException(); }
|
|
980 |
| } |
|
981 |
| |
|
982 |
| }); |
|
983 |
| } |
|
984 |
| |
|
985 |
| |
|
986 |
| |
|
987 |
| |
|
988 |
| |
|
989 |
| |
|
990 |
| |
|
991 |
| |
|
992 |
14
| public Expression cast(final Type target, final Expression e) throws UnsupportedConversionException {
|
|
993 |
14
| Expression result = target.apply(new TypeAbstractVisitor<Expression>() {
|
|
994 |
| |
|
995 |
14
| @Override public Expression forPrimitiveType(PrimitiveType target) {
|
|
996 |
14
| try {
|
|
997 |
14
| Expression result = makePrimitive(e);
|
|
998 |
14
| Type source = NodeProperties.getType(result);
|
|
999 |
| |
|
1000 |
| |
|
1001 |
14
| if (target.equals(BOOLEAN)) {
|
|
1002 |
0
| if (!source.equals(BOOLEAN)) { throw new UnsupportedConversionException(); }
|
|
1003 |
| } |
|
1004 |
14
| else if (target.equals(CHAR) ||
|
|
1005 |
| target.equals(BYTE) || |
|
1006 |
| target.equals(SHORT) || |
|
1007 |
| target.equals(INT) || |
|
1008 |
| target.equals(LONG) || |
|
1009 |
| target.equals(FLOAT) || |
|
1010 |
| target.equals(DOUBLE)) { |
|
1011 |
14
| if ((!source.equals(CHAR)) &&
|
|
1012 |
| (!source.equals(BYTE)) && |
|
1013 |
| (!source.equals(DOUBLE)) && |
|
1014 |
| (!source.equals(FLOAT)) && |
|
1015 |
| (!source.equals(INT)) && |
|
1016 |
| (!source.equals(LONG)) && |
|
1017 |
0
| (!source.equals(SHORT))) { throw new UnsupportedConversionException(); }
|
|
1018 |
| } |
|
1019 |
0
| else { throw new IllegalArgumentException(); }
|
|
1020 |
| |
|
1021 |
| |
|
1022 |
14
| if (!isEqual(target, source)) { NodeProperties.setConvertedType(result, erasedClass(target)); }
|
|
1023 |
14
| return result;
|
|
1024 |
| } |
|
1025 |
0
| catch (UnsupportedConversionException e) { return null; }
|
|
1026 |
| } |
|
1027 |
| |
|
1028 |
0
| @Override public Expression defaultCase(Type target) {
|
|
1029 |
0
| try {
|
|
1030 |
0
| Expression result = makeReference(e);
|
|
1031 |
0
| Type source = NodeProperties.getType(result);
|
|
1032 |
0
| if (isSubtype(source, target)) {
|
|
1033 |
0
| NodeProperties.setAssertedType(result, erasedClass(target));
|
|
1034 |
| } |
|
1035 |
| else { |
|
1036 |
0
| if (!isDisjoint(source, target) && (!_opt.prohibitUncheckedCasts() || validCheckedCast(target, source))) {
|
|
1037 |
0
| NodeProperties.setCheckedType(result, erasedClass(target));
|
|
1038 |
| } |
|
1039 |
0
| else { throw new UnsupportedConversionException(); }
|
|
1040 |
| } |
|
1041 |
0
| return result;
|
|
1042 |
| } |
|
1043 |
0
| catch (UnsupportedConversionException e) { return null; }
|
|
1044 |
| } |
|
1045 |
| }); |
|
1046 |
0
| if (result == null) { throw new UnsupportedConversionException(); }
|
|
1047 |
14
| else { return result; }
|
|
1048 |
| } |
|
1049 |
| |
|
1050 |
| |
|
1051 |
| |
|
1052 |
| |
|
1053 |
| |
|
1054 |
0
| private boolean validCheckedCast(Type target, final Type source) {
|
|
1055 |
0
| return target.apply(new TypeAbstractVisitor<Boolean>() {
|
|
1056 |
0
| @Override public Boolean defaultCase(Type target) { return isReifiable(target); }
|
|
1057 |
0
| @Override public Boolean forParameterizedClassType(ParameterizedClassType target) {
|
|
1058 |
0
| if (isReifiable(target)) { return true; }
|
|
1059 |
0
| else if (isSubtype(target, source)) {
|
|
1060 |
| |
|
1061 |
| |
|
1062 |
0
| ParameterizedClassType wildCapt = capture(parameterize(new RawClassType(target.ofClass())));
|
|
1063 |
0
| Iterable<VariableType> unboundArgs =
|
|
1064 |
| IterUtil.filterInstances(IterUtil.relax(wildCapt.typeArguments()), VariableType.class); |
|
1065 |
0
| Iterable<Type> boundArgs = inferTypeArguments(unboundArgs, EMPTY_TYPE_ITERABLE, wildCapt,
|
|
1066 |
| EMPTY_TYPE_ITERABLE, Option.some(source)); |
|
1067 |
0
| return boundArgs != null && IterUtil.and(boundArgs, target.typeArguments(), new Predicate2<Type, Type>() {
|
|
1068 |
0
| public boolean contains(Type inferred, Type orig) { return isEqual(inferred, orig); }
|
|
1069 |
| }); |
|
1070 |
| } |
|
1071 |
0
| else { return false; }
|
|
1072 |
| } |
|
1073 |
0
| @Override public Boolean forArrayType(ArrayType target) {
|
|
1074 |
0
| if (isArray(source)) { return validCheckedCast(target.ofType(), arrayElementType(source)); }
|
|
1075 |
0
| else { return defaultCase(target); }
|
|
1076 |
| } |
|
1077 |
| }); |
|
1078 |
| } |
|
1079 |
| |
|
1080 |
| |
|
1081 |
| |
|
1082 |
| |
|
1083 |
| |
|
1084 |
| |
|
1085 |
| |
|
1086 |
1408
| public Expression assign(final Type target, final Expression exp) throws UnsupportedConversionException {
|
|
1087 |
1408
| try {
|
|
1088 |
1408
| return target.apply(new TypeAbstractVisitor<Expression>() {
|
|
1089 |
| |
|
1090 |
947
| public Expression defaultCase(final Type target) {
|
|
1091 |
947
| return NodeProperties.getType(exp).apply(new TypeAbstractVisitor<Expression>() {
|
|
1092 |
939
| public Expression defaultCase(Type t) {
|
|
1093 |
| |
|
1094 |
735
| if (isSubtype(t, target)) { return exp; }
|
|
1095 |
204
| else { throw new WrappedException(new UnsupportedConversionException()); }
|
|
1096 |
| } |
|
1097 |
| |
|
1098 |
8
| @Override public Expression forPrimitiveType(PrimitiveType t) {
|
|
1099 |
8
| try {
|
|
1100 |
8
| Expression boxed = makeReference(exp);
|
|
1101 |
8
| if (isSubtype(NodeProperties.getType(boxed), target)) { return exp; }
|
|
1102 |
0
| else { throw new UnsupportedConversionException(); }
|
|
1103 |
| } |
|
1104 |
0
| catch (UnsupportedConversionException e) { throw new WrappedException(e); }
|
|
1105 |
| } |
|
1106 |
| |
|
1107 |
1
| @Override public Expression forCharType(CharType t) {
|
|
1108 |
1
| try {
|
|
1109 |
1
| if (NodeProperties.hasValue(exp)) {
|
|
1110 |
1
| if (isEqual(target, BYTE_CLASS) && inRange(NodeProperties.getValue(exp), BYTE)) {
|
|
1111 |
0
| return makeReference(makeCast(BYTE, exp));
|
|
1112 |
| } |
|
1113 |
1
| else if (isEqual(target, SHORT_CLASS) && inRange(NodeProperties.getValue(exp), SHORT)) {
|
|
1114 |
0
| return makeReference(makeCast(SHORT, exp));
|
|
1115 |
| } |
|
1116 |
| } |
|
1117 |
1
| return forPrimitiveType(t);
|
|
1118 |
| } |
|
1119 |
0
| catch (UnsupportedConversionException e) { throw new WrappedException(e); }
|
|
1120 |
| } |
|
1121 |
| |
|
1122 |
1
| @Override public Expression forByteType(ByteType t) {
|
|
1123 |
1
| try {
|
|
1124 |
1
| if (NodeProperties.hasValue(exp)) {
|
|
1125 |
0
| if (isEqual(target, CHARACTER_CLASS) && inRange(NodeProperties.getValue(exp), CHAR)) {
|
|
1126 |
0
| return makeReference(makeCast(CHAR, exp));
|
|
1127 |
| } |
|
1128 |
| } |
|
1129 |
1
| return forPrimitiveType(t);
|
|
1130 |
| } |
|
1131 |
0
| catch (UnsupportedConversionException e) { throw new WrappedException(e); }
|
|
1132 |
| } |
|
1133 |
| |
|
1134 |
1
| @Override public Expression forShortType(ShortType t) {
|
|
1135 |
1
| try {
|
|
1136 |
1
| if (NodeProperties.hasValue(exp)) {
|
|
1137 |
0
| if (isEqual(target, BYTE_CLASS) && inRange(NodeProperties.getValue(exp), BYTE)) {
|
|
1138 |
0
| return makeReference(makeCast(BYTE, exp));
|
|
1139 |
| } |
|
1140 |
0
| else if (isEqual(target, CHARACTER_CLASS) && inRange(NodeProperties.getValue(exp), CHAR)) {
|
|
1141 |
0
| return makeReference(makeCast(CHAR, exp));
|
|
1142 |
| } |
|
1143 |
| } |
|
1144 |
1
| return forPrimitiveType(t);
|
|
1145 |
| } |
|
1146 |
0
| catch (UnsupportedConversionException e) { throw new WrappedException(e); }
|
|
1147 |
| } |
|
1148 |
| |
|
1149 |
1
| @Override public Expression forIntType(IntType t) {
|
|
1150 |
1
| try {
|
|
1151 |
1
| if (NodeProperties.hasValue(exp)) {
|
|
1152 |
1
| if (isEqual(target, BYTE_CLASS) && inRange(NodeProperties.getValue(exp), BYTE)) {
|
|
1153 |
0
| return makeReference(makeCast(BYTE, exp));
|
|
1154 |
| } |
|
1155 |
1
| else if (isEqual(target, SHORT_CLASS) && inRange(NodeProperties.getValue(exp), SHORT)) {
|
|
1156 |
0
| return makeReference(makeCast(SHORT, exp));
|
|
1157 |
| } |
|
1158 |
1
| else if (isEqual(target, CHARACTER_CLASS) && inRange(NodeProperties.getValue(exp), CHAR)) {
|
|
1159 |
0
| return makeReference(makeCast(CHAR, exp));
|
|
1160 |
| } |
|
1161 |
| } |
|
1162 |
1
| return forPrimitiveType(t);
|
|
1163 |
| } |
|
1164 |
0
| catch (UnsupportedConversionException e) { throw new WrappedException(e); }
|
|
1165 |
| } |
|
1166 |
| }); |
|
1167 |
| } |
|
1168 |
| |
|
1169 |
441
| @Override public Expression forPrimitiveType(PrimitiveType target) {
|
|
1170 |
441
| try {
|
|
1171 |
441
| Expression unboxed = makePrimitive(exp);
|
|
1172 |
441
| Type t = NodeProperties.getType(unboxed);
|
|
1173 |
437
| if (isEqual(t, target)) { return unboxed; }
|
|
1174 |
4
| else if (isSubtype(t, target)) { return makeCast(target, unboxed); }
|
|
1175 |
0
| else { throw new UnsupportedConversionException(); }
|
|
1176 |
| } |
|
1177 |
0
| catch (UnsupportedConversionException e) { throw new WrappedException(e); }
|
|
1178 |
| } |
|
1179 |
| |
|
1180 |
8
| @Override public Expression forCharType(CharType target) { return handleSmallPrimitive(target); }
|
|
1181 |
6
| @Override public Expression forByteType(ByteType target) { return handleSmallPrimitive(target); }
|
|
1182 |
6
| @Override public Expression forShortType(ShortType target) { return handleSmallPrimitive(target); }
|
|
1183 |
| |
|
1184 |
20
| private Expression handleSmallPrimitive(PrimitiveType target) {
|
|
1185 |
20
| try {
|
|
1186 |
20
| Expression unboxed = makePrimitive(exp);
|
|
1187 |
20
| Type t = NodeProperties.getType(unboxed);
|
|
1188 |
20
| if (NodeProperties.hasValue(unboxed) && t instanceof IntegralType && !(t instanceof LongType) &&
|
|
1189 |
6
| inRange(NodeProperties.getValue(unboxed), target)) { return makeCast(target, unboxed); }
|
|
1190 |
11
| else if (isEqual(t, target)) { return unboxed; }
|
|
1191 |
0
| else if (isSubtype(t, target)) { return makeCast(target, unboxed); }
|
|
1192 |
3
| else { throw new UnsupportedConversionException(); }
|
|
1193 |
| } |
|
1194 |
3
| catch (UnsupportedConversionException e) { throw new WrappedException(e); }
|
|
1195 |
| } |
|
1196 |
| |
|
1197 |
| }); |
|
1198 |
| } |
|
1199 |
| catch (WrappedException e) { |
|
1200 |
207
| if (e.getCause() instanceof UnsupportedConversionException) {
|
|
1201 |
207
| throw (UnsupportedConversionException) e.getCause();
|
|
1202 |
| } |
|
1203 |
0
| else { throw e; }
|
|
1204 |
| } |
|
1205 |
| } |
|
1206 |
| |
|
1207 |
| |
|
1208 |
| |
|
1209 |
| |
|
1210 |
| |
|
1211 |
| |
|
1212 |
| |
|
1213 |
| |
|
1214 |
204
| private Expression makeCast(Type target, Expression e) {
|
|
1215 |
204
| Expression result = new CastExpression(null, e, e.getSourceInfo());
|
|
1216 |
204
| if (isPrimitive(target)) {
|
|
1217 |
27
| if (!isEqual(target, NodeProperties.getType(e))) {
|
|
1218 |
21
| NodeProperties.setConvertedType(result, erasedClass(target));
|
|
1219 |
21
| if (NodeProperties.hasValue(e)) {
|
|
1220 |
1
| Object orig = NodeProperties.getValue(e);
|
|
1221 |
1
| Class<?> t = NodeProperties.getConvertedType(result).value();
|
|
1222 |
1
| NodeProperties.setValue(result, ExpressionEvaluator.convert(orig, t));
|
|
1223 |
| } |
|
1224 |
| } |
|
1225 |
| else { |
|
1226 |
6
| if (NodeProperties.hasValue(e)) { NodeProperties.setValue(result, NodeProperties.getValue(e)); }
|
|
1227 |
| } |
|
1228 |
| } |
|
1229 |
| else { |
|
1230 |
| |
|
1231 |
| } |
|
1232 |
| |
|
1233 |
204
| NodeProperties.setType(result, target);
|
|
1234 |
204
| return result;
|
|
1235 |
| } |
|
1236 |
| |
|
1237 |
20
| private Expression makeArray(ArrayType arrayType, Iterable<? extends Expression> elements) {
|
|
1238 |
20
| Thunk<Class<?>> erasedType = erasedClass(arrayType);
|
|
1239 |
20
| TypeName tn = TypeUtil.makeEmptyTypeName();
|
|
1240 |
| |
|
1241 |
| |
|
1242 |
| |
|
1243 |
20
| NodeProperties.setType(tn, arrayType.ofType());
|
|
1244 |
20
| ArrayInitializer init = new ArrayInitializer(CollectUtil.makeList(elements));
|
|
1245 |
20
| NodeProperties.setType(init, arrayType);
|
|
1246 |
20
| NodeProperties.setErasedType(init, erasedType);
|
|
1247 |
20
| Expression result = new ArrayAllocation(tn, new ArrayAllocation.TypeDescriptor(new ArrayList<Expression>(0),
|
|
1248 |
| 1, init, SourceInfo.NONE)); |
|
1249 |
20
| NodeProperties.setType(result, arrayType);
|
|
1250 |
20
| NodeProperties.setErasedType(result, erasedType);
|
|
1251 |
20
| return result;
|
|
1252 |
| } |
|
1253 |
| |
|
1254 |
| |
|
1255 |
| |
|
1256 |
| |
|
1257 |
| |
|
1258 |
6
| private boolean inRange(final Object value, Type t) {
|
|
1259 |
0
| if (isReference(t)) { return value == null; }
|
|
1260 |
6
| else return t.apply(new TypeAbstractVisitor<Boolean>() {
|
|
1261 |
0
| public Boolean defaultCase(Type t) { return false; }
|
|
1262 |
0
| @Override public Boolean forBooleanType(BooleanType t) { return value instanceof Boolean; }
|
|
1263 |
6
| @Override public Boolean forCharType(CharType t) { return checkNumber(Character.MIN_VALUE, Character.MAX_VALUE); }
|
|
1264 |
0
| @Override public Boolean forByteType(ByteType t) { return checkNumber(Byte.MIN_VALUE, Byte.MAX_VALUE); }
|
|
1265 |
0
| @Override public Boolean forShortType(ShortType t) { return checkNumber(Short.MIN_VALUE, Short.MAX_VALUE); }
|
|
1266 |
0
| @Override public Boolean forIntType(IntType t) { return checkNumber(Integer.MIN_VALUE, Integer.MAX_VALUE); }
|
|
1267 |
0
| @Override public Boolean forLongType(LongType t) { return checkNumber(Long.MIN_VALUE, Long.MAX_VALUE); }
|
|
1268 |
6
| private Boolean checkNumber(long lowerBound, long upperBound) {
|
|
1269 |
6
| if (value instanceof Number && !(value instanceof Float) && !(value instanceof Double)) {
|
|
1270 |
0
| long val = ((Number) value).longValue();
|
|
1271 |
0
| return lowerBound <= val && val <= upperBound;
|
|
1272 |
| } |
|
1273 |
6
| else if (value instanceof Character) {
|
|
1274 |
6
| long val = ((Character) value).charValue();
|
|
1275 |
6
| return lowerBound <= val && val <= upperBound;
|
|
1276 |
| } |
|
1277 |
0
| else { return false; }
|
|
1278 |
| } |
|
1279 |
| }); |
|
1280 |
| } |
|
1281 |
| |
|
1282 |
| |
|
1283 |
37652
| protected Type immediateSupertype(ClassType t) {
|
|
1284 |
14558
| if (t.equals(OBJECT)) { return null; }
|
|
1285 |
| else { |
|
1286 |
23094
| final Iterable<Type> declaredSupers = t.ofClass().declaredSupertypes();
|
|
1287 |
13488
| if (IterUtil.isEmpty(declaredSupers)) { return OBJECT; }
|
|
1288 |
| else { |
|
1289 |
9606
| Iterable<? extends Type> instantiatedSupers = t.apply(new TypeAbstractVisitor<Iterable<? extends Type>>() {
|
|
1290 |
2870
| @Override public Iterable<? extends Type> defaultCase(Type t) { return declaredSupers; }
|
|
1291 |
4238
| @Override public Iterable<? extends Type> forRawClassType(RawClassType t) {
|
|
1292 |
4238
| return IterUtil.mapSnapshot(declaredSupers, ERASE);
|
|
1293 |
| } |
|
1294 |
2498
| @Override public Iterable<? extends Type> forParameterizedClassType(ParameterizedClassType t) {
|
|
1295 |
2498
| ParameterizedClassType tCap = capture(t);
|
|
1296 |
2498
| DJClass c = tCap.ofClass();
|
|
1297 |
2498
| return substitute(c.declaredSupertypes(), SymbolUtil.allTypeParameters(c), tCap.typeArguments());
|
|
1298 |
| } |
|
1299 |
| }); |
|
1300 |
3256
| if (IterUtil.sizeOf(instantiatedSupers, 2) > 1) { return new IntersectionType(instantiatedSupers); }
|
|
1301 |
6350
| else { return IterUtil.first(instantiatedSupers); }
|
|
1302 |
| } |
|
1303 |
| } |
|
1304 |
| } |
|
1305 |
| |
|
1306 |
| |
|
1307 |
| |
|
1308 |
| |
|
1309 |
| |
|
1310 |
| |
|
1311 |
| |
|
1312 |
| |
|
1313 |
| |
|
1314 |
| |
|
1315 |
| |
|
1316 |
| |
|
1317 |
| |
|
1318 |
552
| public ConstructorInvocation lookupConstructor(final Type t, final Iterable<? extends Type> typeArgs,
|
|
1319 |
| final Iterable<? extends Expression> args, |
|
1320 |
| final Option<Type> expected, final Access.Module accessModule) |
|
1321 |
| throws InvalidTypeArgumentException, UnmatchedLookupException { |
|
1322 |
552
| debug.logStart(new String[]{"t","typeArgs","arg types","expected"},
|
|
1323 |
552
| wrap(t), wrap(typeArgs), wrap(IterUtil.map(args, NodeProperties.NODE_TYPE)), wrap(expected)); try {
|
|
1324 |
| |
|
1325 |
552
| Iterable<DJConstructor> constructors =
|
|
1326 |
| t.apply(new TypeAbstractVisitor<Iterable<DJConstructor>>() { |
|
1327 |
0
| @Override public Iterable<DJConstructor> defaultCase(Type t) { return IterUtil.empty(); }
|
|
1328 |
339
| @Override public Iterable<DJConstructor> forSimpleClassType(SimpleClassType t) {
|
|
1329 |
339
| return t.ofClass().declaredConstructors();
|
|
1330 |
| } |
|
1331 |
0
| @Override public Iterable<DJConstructor> forRawClassType(RawClassType t) {
|
|
1332 |
0
| return IterUtil.mapSnapshot(t.ofClass().declaredConstructors(), new Lambda<DJConstructor, DJConstructor>() {
|
|
1333 |
0
| public DJConstructor value(DJConstructor k) {
|
|
1334 |
| |
|
1335 |
0
| return new ErasedConstructor(k);
|
|
1336 |
| } |
|
1337 |
| }); |
|
1338 |
| } |
|
1339 |
213
| @Override public Iterable<DJConstructor> forParameterizedClassType(ParameterizedClassType t) {
|
|
1340 |
213
| final Iterable<VariableType> classTParams = SymbolUtil.allTypeParameters(t.ofClass());
|
|
1341 |
213
| final Iterable<? extends Type> classTArgs = capture(t).typeArguments();
|
|
1342 |
213
| return IterUtil.mapSnapshot(t.ofClass().declaredConstructors(), new Lambda<DJConstructor, DJConstructor>() {
|
|
1343 |
220
| public DJConstructor value(DJConstructor k) {
|
|
1344 |
220
| return new InstantiatedConstructor(k, classTParams, classTArgs);
|
|
1345 |
| } |
|
1346 |
| }); |
|
1347 |
| } |
|
1348 |
| }); |
|
1349 |
| |
|
1350 |
552
| Iterable<DJConstructor> accessible = IterUtil.filter(constructors, new Predicate<DJConstructor>() {
|
|
1351 |
1216
| public boolean contains(DJConstructor k) { return accessible(k, accessModule); }
|
|
1352 |
| }); |
|
1353 |
552
| Iterable<FunctionInvocationCandidate<DJConstructor>> cs = bestInvocations(accessible, typeArgs, args, expected);
|
|
1354 |
| |
|
1355 |
552
| int matches = IterUtil.sizeOf(cs);
|
|
1356 |
1
| if (matches == 0) { throw new UnmatchedFunctionLookupException(constructors); }
|
|
1357 |
551
| else if (matches > 1) {
|
|
1358 |
0
| Iterable<DJConstructor> ks = IterUtil.map(cs, new Lambda<FunctionInvocationCandidate<DJConstructor>,
|
|
1359 |
| DJConstructor>() { |
|
1360 |
0
| public DJConstructor value(FunctionInvocationCandidate<DJConstructor> c) { return c.function(); }
|
|
1361 |
| }); |
|
1362 |
0
| throw new AmbiguousFunctionLookupException(ks);
|
|
1363 |
| } |
|
1364 |
| else { |
|
1365 |
551
| FunctionInvocationCandidate<DJConstructor> c = IterUtil.first(cs);
|
|
1366 |
551
| DJConstructor k = c.function();
|
|
1367 |
551
| SubstitutionMap sigma = c.substitution();
|
|
1368 |
551
| return new ConstructorInvocation(k, c.typeArguments(), c.arguments(), substitute(k.thrownTypes(), sigma));
|
|
1369 |
| } |
|
1370 |
| |
|
1371 |
552
| } finally { debug.logEnd(); }
|
|
1372 |
| } |
|
1373 |
| |
|
1374 |
0
| public boolean containsMethod(Type t, String name, Access.Module accessModule) {
|
|
1375 |
0
| return new MethodFinder(name, accessModule, false).hasMatch(t);
|
|
1376 |
| } |
|
1377 |
0
| public boolean containsStaticMethod(Type t, String name, Access.Module accessModule) {
|
|
1378 |
0
| return new MethodFinder(name, accessModule, true).hasMatch(t);
|
|
1379 |
| } |
|
1380 |
| |
|
1381 |
107
| public ObjectMethodInvocation lookupMethod(Expression object, String name,
|
|
1382 |
| Iterable<? extends Type> typeArgs, |
|
1383 |
| Iterable<? extends Expression> args, |
|
1384 |
| Option<Type> expected, Access.Module accessModule) |
|
1385 |
| throws InvalidTypeArgumentException, UnmatchedLookupException { |
|
1386 |
107
| Type t = NodeProperties.getType(object);
|
|
1387 |
107
| FunctionInvocationCandidate<DJMethod> result =
|
|
1388 |
| new MethodFinder(name, accessModule, false).findSingleMethod(t, typeArgs, args, expected); |
|
1389 |
97
| DJMethod m = result.function();
|
|
1390 |
97
| SubstitutionMap sigma = result.substitution();
|
|
1391 |
| |
|
1392 |
97
| return new ObjectMethodInvocation(m, substitute(m.returnType(), sigma), object, result.typeArguments(),
|
|
1393 |
| result.arguments(), substitute(m.thrownTypes(), sigma)); |
|
1394 |
| } |
|
1395 |
| |
|
1396 |
179
| public StaticMethodInvocation lookupStaticMethod(Type t, String name,
|
|
1397 |
| Iterable<? extends Type> typeArgs, |
|
1398 |
| Iterable<? extends Expression> args, |
|
1399 |
| Option<Type> expected, Access.Module accessModule) |
|
1400 |
| throws InvalidTypeArgumentException, UnmatchedLookupException { |
|
1401 |
179
| FunctionInvocationCandidate<DJMethod> result =
|
|
1402 |
| new MethodFinder(name, accessModule, true).findSingleMethod(t, typeArgs, args, expected); |
|
1403 |
173
| DJMethod m = result.function();
|
|
1404 |
173
| SubstitutionMap sigma = result.substitution();
|
|
1405 |
173
| return new StaticMethodInvocation(m, substitute(m.returnType(), sigma), result.typeArguments(),
|
|
1406 |
| result.arguments(), substitute(m.thrownTypes(), sigma)); |
|
1407 |
| } |
|
1408 |
| |
|
1409 |
260
| public boolean containsField(Type t, String name, Access.Module accessModule) {
|
|
1410 |
260
| return containsField(t, name, accessModule, false);
|
|
1411 |
| } |
|
1412 |
0
| public boolean containsStaticField(Type t, String name, Access.Module accessModule) {
|
|
1413 |
0
| return containsField(t, name, accessModule, true);
|
|
1414 |
| } |
|
1415 |
260
| private boolean containsField(Type t, String name, Access.Module accessModule, boolean onlyStatic) {
|
|
1416 |
260
| FieldFinder<FieldReference> finder = new FieldFinder<FieldReference>(name, accessModule, onlyStatic) {
|
|
1417 |
254
| protected FieldReference makeFieldReference(Type t, DJField f) {
|
|
1418 |
254
| return new FieldReference(f, BOTTOM) {};
|
|
1419 |
| } |
|
1420 |
| }; |
|
1421 |
260
| return finder.hasMatch(t);
|
|
1422 |
| } |
|
1423 |
| |
|
1424 |
177
| public ObjectFieldReference lookupField(final Expression object, String name, Access.Module accessModule)
|
|
1425 |
| throws UnmatchedLookupException { |
|
1426 |
177
| FieldFinder<ObjectFieldReference> finder = new FieldFinder<ObjectFieldReference>(name, accessModule, false) {
|
|
1427 |
177
| public ObjectFieldReference makeFieldReference(Type t, DJField f) {
|
|
1428 |
177
| return new ObjectFieldReference(f, fieldType(f, t), makeCast(t, object));
|
|
1429 |
| } |
|
1430 |
| }; |
|
1431 |
177
| return finder.findSingleField(NodeProperties.getType(object));
|
|
1432 |
| } |
|
1433 |
| |
|
1434 |
1
| public StaticFieldReference lookupStaticField(Type t, String name, Access.Module accessModule)
|
|
1435 |
| throws UnmatchedLookupException { |
|
1436 |
1
| FieldFinder<StaticFieldReference> finder = new FieldFinder<StaticFieldReference>(name, accessModule, true) {
|
|
1437 |
1
| public StaticFieldReference makeFieldReference(Type t, DJField f) {
|
|
1438 |
1
| return new StaticFieldReference(f, fieldType(f, t));
|
|
1439 |
| } |
|
1440 |
| }; |
|
1441 |
1
| return finder.findSingleField(t);
|
|
1442 |
| } |
|
1443 |
| |
|
1444 |
178
| private Type fieldType(final DJField f, Type declaringType) {
|
|
1445 |
178
| Type dynamicContext;
|
|
1446 |
178
| if (f.isStatic()) {
|
|
1447 |
1
| if (declaringType instanceof ClassType) {
|
|
1448 |
1
| dynamicContext = SymbolUtil.dynamicOuterClassType((ClassType) declaringType);
|
|
1449 |
| } |
|
1450 |
0
| else { dynamicContext = null; }
|
|
1451 |
| } |
|
1452 |
177
| else { dynamicContext = declaringType; }
|
|
1453 |
1
| if (dynamicContext == null) { return f.type(); }
|
|
1454 |
| else { |
|
1455 |
177
| return dynamicContext.apply(new TypeAbstractVisitor<Type>() {
|
|
1456 |
108
| @Override public Type defaultCase(Type dynamicContext) { return f.type(); }
|
|
1457 |
0
| @Override public Type forRawClassType(RawClassType dynamicContext) {
|
|
1458 |
| |
|
1459 |
0
| return erase(f.type());
|
|
1460 |
| } |
|
1461 |
69
| @Override public Type forParameterizedClassType(ParameterizedClassType dynamicContext) {
|
|
1462 |
69
| ParameterizedClassType dynamicContextCap = capture(dynamicContext);
|
|
1463 |
69
| Iterable<VariableType> tparams = SymbolUtil.allTypeParameters(dynamicContextCap.ofClass());
|
|
1464 |
69
| return substitute(f.type(), tparams, dynamicContextCap.typeArguments());
|
|
1465 |
| } |
|
1466 |
| }); |
|
1467 |
| } |
|
1468 |
| } |
|
1469 |
| |
|
1470 |
524
| public boolean containsClass(Type t, String name, Access.Module accessModule) {
|
|
1471 |
524
| return new ClassFinder(name, EMPTY_TYPE_ITERABLE, accessModule, false).hasMatch(t);
|
|
1472 |
| } |
|
1473 |
| |
|
1474 |
0
| public boolean containsStaticClass(Type t, String name, Access.Module accessModule) {
|
|
1475 |
0
| return new ClassFinder(name, EMPTY_TYPE_ITERABLE, accessModule, true).hasMatch(t);
|
|
1476 |
| } |
|
1477 |
| |
|
1478 |
0
| public ClassType lookupClass(Expression object, String name, Iterable<? extends Type> typeArgs,
|
|
1479 |
| Access.Module accessModule) |
|
1480 |
| throws InvalidTypeArgumentException, UnmatchedLookupException { |
|
1481 |
0
| return new ClassFinder(name, typeArgs, accessModule, false).findSingleClass(NodeProperties.getType(object));
|
|
1482 |
| } |
|
1483 |
| |
|
1484 |
0
| public ClassType lookupClass(Type t, String name, Iterable<? extends Type> typeArgs, Access.Module accessModule)
|
|
1485 |
| throws InvalidTypeArgumentException, UnmatchedLookupException { |
|
1486 |
0
| return new ClassFinder(name, typeArgs, accessModule, false).findSingleClass(t);
|
|
1487 |
| } |
|
1488 |
| |
|
1489 |
0
| public ClassType lookupStaticClass(Type t, final String name, final Iterable<? extends Type> typeArgs,
|
|
1490 |
| Access.Module accessModule) |
|
1491 |
| throws InvalidTypeArgumentException, UnmatchedLookupException { |
|
1492 |
0
| return new ClassFinder(name, typeArgs, accessModule, true).findSingleClass(t);
|
|
1493 |
| } |
|
1494 |
| |
|
1495 |
| |
|
1496 |
| |
|
1497 |
| |
|
1498 |
| |
|
1499 |
1978
| private boolean accessible(Access.Limited symbol, Access.Module accessingModule) {
|
|
1500 |
1978
| switch (symbol.accessibility()) {
|
|
1501 |
322
| case PRIVATE:
|
|
1502 |
322
| return (!_opt.enforcePrivateAccess() && !_opt.enforceAllAccess()) ||
|
|
1503 |
| symbol.accessModule().equals(accessingModule); |
|
1504 |
0
| case PACKAGE:
|
|
1505 |
0
| return !_opt.enforceAllAccess() ||
|
|
1506 |
| symbol.accessModule().packageName().equals(accessingModule.packageName()); |
|
1507 |
0
| case PROTECTED:
|
|
1508 |
| |
|
1509 |
0
| return !_opt.enforceAllAccess() || true;
|
|
1510 |
1656
| default:
|
|
1511 |
1656
| return true;
|
|
1512 |
| } |
|
1513 |
| } |
|
1514 |
| |
|
1515 |
| |
|
1516 |
| |
|
1517 |
| |
|
1518 |
| |
|
1519 |
| |
|
1520 |
| |
|
1521 |
531
| protected boolean inBounds(Iterable<? extends VariableType> params, Iterable<? extends Type> args) {
|
|
1522 |
531
| SubstitutionMap sigma = new SubstitutionMap(params, args);
|
|
1523 |
531
| for (Pair<VariableType, Type> pair : IterUtil.zip(params, args)) {
|
|
1524 |
531
| VariableType param = pair.first();
|
|
1525 |
531
| Type arg = pair.second();
|
|
1526 |
0
| if (!isSubtype(substitute(param.symbol().lowerBound(), sigma), arg)) { return false; }
|
|
1527 |
2
| if (!isSubtype(arg, substitute(param.symbol().upperBound(), sigma))) { return false; }
|
|
1528 |
| } |
|
1529 |
529
| return true;
|
|
1530 |
| } |
|
1531 |
| |
|
1532 |
| |
|
1533 |
| private class StandardTypePrinter implements TypePrinter { |
|
1534 |
| |
|
1535 |
| private final Map<VariableType, String> _names = new HashMap<VariableType, String>(); |
|
1536 |
| int _captureVars = 0; |
|
1537 |
| |
|
1538 |
75
| public String print(Type t) {
|
|
1539 |
75
| Visitor v = new Visitor();
|
|
1540 |
75
| v.run(t);
|
|
1541 |
75
| v.appendConstraints();
|
|
1542 |
75
| return v.result();
|
|
1543 |
| } |
|
1544 |
| |
|
1545 |
34
| public String print(Iterable<? extends Type> ts) {
|
|
1546 |
34
| Visitor v = new Visitor();
|
|
1547 |
34
| v.runOnList(ts, ", ");
|
|
1548 |
34
| v.appendConstraints();
|
|
1549 |
34
| return v.result();
|
|
1550 |
| } |
|
1551 |
| |
|
1552 |
17
| public String print(Function f) {
|
|
1553 |
17
| Visitor v = new Visitor();
|
|
1554 |
17
| if (!IterUtil.isEmpty(f.typeParameters())) {
|
|
1555 |
2
| v.append("<");
|
|
1556 |
2
| v.runOnList(f.typeParameters(), ", ");
|
|
1557 |
2
| v.append("> ");
|
|
1558 |
| } |
|
1559 |
17
| if (!(f instanceof DJConstructor)) {
|
|
1560 |
16
| v.run(f.returnType());
|
|
1561 |
16
| v.append(" ");
|
|
1562 |
| } |
|
1563 |
17
| v.append(f.declaredName());
|
|
1564 |
17
| v.append("(");
|
|
1565 |
17
| v.runOnList(SymbolUtil.parameterTypes(f), ", ");
|
|
1566 |
17
| v.append(")");
|
|
1567 |
17
| v.appendConstraints();
|
|
1568 |
17
| return v.result();
|
|
1569 |
| } |
|
1570 |
| |
|
1571 |
| private class Visitor extends TypeVisitorRunnable1 { |
|
1572 |
| private final StringBuilder _result = new StringBuilder(); |
|
1573 |
| private final RecursionStack<Type> _stack = new RecursionStack<Type>(); |
|
1574 |
| |
|
1575 |
| private final List<VariableType> _boundedVars = new ArrayList<VariableType>(); |
|
1576 |
| private final Set<VariableType> _seenVars = new HashSet<VariableType>(); |
|
1577 |
| |
|
1578 |
126
| public String result() { return _result.toString(); }
|
|
1579 |
| |
|
1580 |
71
| public void append(String s) { _result.append(s); }
|
|
1581 |
| |
|
1582 |
126
| public void appendConstraints() {
|
|
1583 |
126
| if (!_boundedVars.isEmpty()) {
|
|
1584 |
12
| _result.append(" [");
|
|
1585 |
| |
|
1586 |
12
| for (int i = 0; i < _boundedVars.size(); i++) {
|
|
1587 |
0
| if (i > 0) { _result.append("; "); }
|
|
1588 |
12
| VariableType v = _boundedVars.get(i);
|
|
1589 |
12
| Type upper = v.symbol().upperBound();
|
|
1590 |
12
| Type lower = v.symbol().lowerBound();
|
|
1591 |
12
| boolean printUpper = !isEqual(upper, OBJECT) ;
|
|
1592 |
12
| boolean printLower = !isEqual(lower, NULL) ;
|
|
1593 |
12
| if (printUpper) {
|
|
1594 |
9
| _result.append(nameForVariable(v));
|
|
1595 |
9
| _result.append(" <: ");
|
|
1596 |
9
| run(upper);
|
|
1597 |
| } |
|
1598 |
12
| if (printLower) {
|
|
1599 |
4
| if (printUpper) { _result.append(", "); }
|
|
1600 |
7
| _result.append(nameForVariable(v));
|
|
1601 |
7
| _result.append(" :> ");
|
|
1602 |
7
| run(lower);
|
|
1603 |
| } |
|
1604 |
| } |
|
1605 |
12
| _result.append("]");
|
|
1606 |
| } |
|
1607 |
| } |
|
1608 |
| |
|
1609 |
38
| private String nameForVariable(VariableType t) {
|
|
1610 |
38
| String name = _names.get(t);
|
|
1611 |
38
| if (name == null) {
|
|
1612 |
11
| if (t.symbol().generated()) { _captureVars++; name = "?T" + _captureVars; }
|
|
1613 |
2
| else { name = t.symbol().name(); }
|
|
1614 |
13
| _names.put(t, name);
|
|
1615 |
| } |
|
1616 |
38
| if (!_seenVars.contains(t)) {
|
|
1617 |
17
| _seenVars.add(t);
|
|
1618 |
| |
|
1619 |
17
| Type upper = t.symbol().upperBound();
|
|
1620 |
17
| Type lower = t.symbol().lowerBound();
|
|
1621 |
17
| boolean printUpper = !isEqual(upper, OBJECT) ;
|
|
1622 |
17
| boolean printLower = !isEqual(lower, NULL) ;
|
|
1623 |
12
| if (printUpper || printLower) { _boundedVars.add(t); }
|
|
1624 |
| } |
|
1625 |
38
| return name;
|
|
1626 |
| } |
|
1627 |
| |
|
1628 |
| |
|
1629 |
| |
|
1630 |
| |
|
1631 |
| |
|
1632 |
214
| @Override public void run(final Type t) {
|
|
1633 |
| |
|
1634 |
| |
|
1635 |
214
| Runnable recur = new Runnable() { public void run() { t.apply(Visitor.this); } };
|
|
1636 |
0
| Runnable dontRecur = new Runnable() { public void run() { _result.append("..."); } };
|
|
1637 |
| |
|
1638 |
214
| _stack.run(recur, dontRecur, t);
|
|
1639 |
| } |
|
1640 |
| |
|
1641 |
53
| public void runOnList(Iterable<? extends Type> ts, String delim) {
|
|
1642 |
53
| boolean first = true;
|
|
1643 |
53
| for (Type t : ts) {
|
|
1644 |
14
| if (!first) { _result.append(delim); }
|
|
1645 |
46
| first = false;
|
|
1646 |
46
| run(t);
|
|
1647 |
| } |
|
1648 |
| } |
|
1649 |
| |
|
1650 |
0
| public void forBooleanType(BooleanType t) { _result.append("boolean"); }
|
|
1651 |
1
| public void forCharType(CharType t) { _result.append("char"); }
|
|
1652 |
1
| public void forByteType(ByteType t) { _result.append("byte"); }
|
|
1653 |
1
| public void forShortType(ShortType t) { _result.append("short"); }
|
|
1654 |
24
| public void forIntType(IntType t) { _result.append("int"); }
|
|
1655 |
0
| public void forLongType(LongType t) { _result.append("long"); }
|
|
1656 |
0
| public void forFloatType(FloatType t) { _result.append("float"); }
|
|
1657 |
0
| public void forDoubleType(DoubleType t) { _result.append("double"); }
|
|
1658 |
0
| public void forNullType(NullType t) { _result.append("(null)"); }
|
|
1659 |
6
| public void forVoidType(VoidType t) { _result.append("void"); }
|
|
1660 |
0
| public void forTopType(TopType t) { _result.append("(top)"); }
|
|
1661 |
0
| public void forBottomType(BottomType t) { _result.append("(bottom)"); }
|
|
1662 |
| |
|
1663 |
4
| public void forSimpleArrayType(SimpleArrayType t) {
|
|
1664 |
4
| run(t.ofType());
|
|
1665 |
4
| _result.append("[]");
|
|
1666 |
| } |
|
1667 |
| |
|
1668 |
4
| public void forVarargArrayType(VarargArrayType t) {
|
|
1669 |
4
| run(t.ofType());
|
|
1670 |
4
| _result.append("...");
|
|
1671 |
| } |
|
1672 |
| |
|
1673 |
101
| public void forSimpleClassType(SimpleClassType t) { appendClassName(t.ofClass()); }
|
|
1674 |
| |
|
1675 |
0
| public void forRawClassType(RawClassType t) {
|
|
1676 |
0
| _result.append("raw ");
|
|
1677 |
0
| appendClassName(t.ofClass());
|
|
1678 |
| } |
|
1679 |
| |
|
1680 |
41
| public void forParameterizedClassType(ParameterizedClassType t) {
|
|
1681 |
41
| Iterator<DJClass> classes = SymbolUtil.outerClassChain(t.ofClass()).iterator();
|
|
1682 |
41
| Iterator<? extends Type> targs = t.typeArguments().iterator();
|
|
1683 |
41
| DJClass c = classes.next();
|
|
1684 |
41
| appendClassName(c);
|
|
1685 |
41
| DJClass inner;
|
|
1686 |
41
| while (c != null) {
|
|
1687 |
41
| inner = classes.hasNext() ? classes.next() : null;
|
|
1688 |
41
| if (inner == null || !inner.isStatic()) {
|
|
1689 |
41
| Iterable<VariableType> params = c.declaredTypeParameters();
|
|
1690 |
41
| if (!IterUtil.isEmpty(params)) {
|
|
1691 |
41
| _result.append("<");
|
|
1692 |
41
| boolean firstParam = true;
|
|
1693 |
41
| for (VariableType param : params) {
|
|
1694 |
0
| if (!firstParam) { _result.append(", "); }
|
|
1695 |
41
| firstParam = false;
|
|
1696 |
41
| run(targs.next());
|
|
1697 |
| } |
|
1698 |
41
| _result.append(">");
|
|
1699 |
| } |
|
1700 |
| } |
|
1701 |
0
| if (inner != null) { _result.append("."); _result.append(inner.declaredName()); }
|
|
1702 |
41
| c = inner;
|
|
1703 |
| } |
|
1704 |
| } |
|
1705 |
| |
|
1706 |
142
| private void appendClassName(DJClass c) {
|
|
1707 |
142
| if (c.isAnonymous()) {
|
|
1708 |
0
| _result.append("anonymous ");
|
|
1709 |
0
| runOnList(c.declaredSupertypes(), " & ");
|
|
1710 |
| } |
|
1711 |
142
| else { _result.append(SymbolUtil.shortName(c)); }
|
|
1712 |
| } |
|
1713 |
| |
|
1714 |
22
| public void forVariableType(VariableType t) {
|
|
1715 |
22
| _result.append(nameForVariable(t));
|
|
1716 |
| } |
|
1717 |
| |
|
1718 |
0
| public void forIntersectionType(IntersectionType t) {
|
|
1719 |
0
| int size = IterUtil.sizeOf(t.ofTypes());
|
|
1720 |
0
| if (size == 0) { _result.append("(empty intersect)"); }
|
|
1721 |
0
| else if (size == 1) {
|
|
1722 |
0
| _result.append("(intersect ");
|
|
1723 |
0
| run(IterUtil.first(t.ofTypes()));
|
|
1724 |
0
| _result.append(")");
|
|
1725 |
| } |
|
1726 |
0
| else { runOnList(t.ofTypes(), " & "); }
|
|
1727 |
| } |
|
1728 |
| |
|
1729 |
0
| public void forUnionType(UnionType t) {
|
|
1730 |
0
| int size = IterUtil.sizeOf(t.ofTypes());
|
|
1731 |
0
| if (size == 0) { _result.append("(empty union)"); }
|
|
1732 |
0
| else if (size == 1) {
|
|
1733 |
0
| _result.append("(union ");
|
|
1734 |
0
| run(IterUtil.first(t.ofTypes()));
|
|
1735 |
0
| _result.append(")");
|
|
1736 |
| } |
|
1737 |
0
| else { runOnList(t.ofTypes(), " | "); }
|
|
1738 |
| } |
|
1739 |
| |
|
1740 |
9
| public void forWildcard(Wildcard t) {
|
|
1741 |
9
| _result.append("?");
|
|
1742 |
9
| if (!isEqual(t.symbol().upperBound(), OBJECT)) {
|
|
1743 |
6
| _result.append(" extends ");
|
|
1744 |
6
| run(t.symbol().upperBound());
|
|
1745 |
| } |
|
1746 |
9
| if (!isEqual(t.symbol().lowerBound(), NULL)) {
|
|
1747 |
6
| _result.append(" super ");
|
|
1748 |
6
| run(t.symbol().lowerBound());
|
|
1749 |
| } |
|
1750 |
| } |
|
1751 |
| |
|
1752 |
| } |
|
1753 |
| |
|
1754 |
| } |
|
1755 |
| |
|
1756 |
| |
|
1757 |
| |
|
1758 |
| |
|
1759 |
| |
|
1760 |
| |
|
1761 |
| private abstract class MemberFinder<T> { |
|
1762 |
| |
|
1763 |
784
| public boolean hasMatch(Type t) { return !IterUtil.isEmpty(findFirst(t)); }
|
|
1764 |
| |
|
1765 |
| |
|
1766 |
| |
|
1767 |
| |
|
1768 |
962
| public PredicateSet<T> findFirst(Type t) { return find(t, false); }
|
|
1769 |
| |
|
1770 |
| |
|
1771 |
286
| public PredicateSet<T> findAll(Type t) { return find(t, true); }
|
|
1772 |
| |
|
1773 |
| |
|
1774 |
| protected abstract Iterable<T> declaredMatches(Type t); |
|
1775 |
| |
|
1776 |
| |
|
1777 |
| protected abstract boolean inherits(Type child, PredicateSet<T> childMatches, T match); |
|
1778 |
| |
|
1779 |
2633
| private PredicateSet<T> find(final Type t, final boolean findAll) {
|
|
1780 |
2633
| debug.logStart("t", wrap(t)); try {
|
|
1781 |
| |
|
1782 |
2633
| final PredicateSet<T> childMatches = CollectUtil.asPredicateSet(declaredMatches(t));
|
|
1783 |
2633
| if (!findAll && !IterUtil.isEmpty(childMatches)) {
|
|
1784 |
| |
|
1785 |
432
| return CollectUtil.makeSet(childMatches);
|
|
1786 |
| } |
|
1787 |
| else { |
|
1788 |
2201
| PredicateSet<T> fromSupers = t.apply(new TypeAbstractVisitor<PredicateSet<T>>() {
|
|
1789 |
| |
|
1790 |
0
| public PredicateSet<T> defaultCase(Type t) { return CollectUtil.emptySet(); }
|
|
1791 |
| |
|
1792 |
0
| @Override public PredicateSet<T> forArrayType(ArrayType t) {
|
|
1793 |
0
| return find(CLONEABLE_AND_SERIALIZABLE, findAll);
|
|
1794 |
| } |
|
1795 |
| |
|
1796 |
2099
| @Override public PredicateSet<T> forClassType(ClassType t) {
|
|
1797 |
2099
| Type superT = immediateSupertype(t);
|
|
1798 |
968
| if (superT == null) { return CollectUtil.emptySet(); }
|
|
1799 |
1131
| else { return find(superT, findAll); }
|
|
1800 |
| } |
|
1801 |
| |
|
1802 |
0
| @Override public PredicateSet<T> forVariableType(VariableType t) {
|
|
1803 |
0
| return find(t.symbol().upperBound(), findAll);
|
|
1804 |
| } |
|
1805 |
| |
|
1806 |
102
| @Override public PredicateSet<T> forIntersectionType(IntersectionType t) {
|
|
1807 |
102
| PredicateSet<T> result = CollectUtil.emptySet();
|
|
1808 |
102
| for (Type tSup : t.ofTypes()) {
|
|
1809 |
254
| PredicateSet<T> forSup = find(tSup, findAll);
|
|
1810 |
254
| result = CollectUtil.union(result, forSup);
|
|
1811 |
| } |
|
1812 |
102
| return result;
|
|
1813 |
| } |
|
1814 |
| |
|
1815 |
0
| @Override public PredicateSet<T> forUnionType(UnionType t) {
|
|
1816 |
0
| Iterable<? extends Type> sups = t.ofTypes();
|
|
1817 |
0
| if (IterUtil.isEmpty(sups)) { return CollectUtil.emptySet(); }
|
|
1818 |
| else { |
|
1819 |
0
| PredicateSet<T> result = find(IterUtil.first(sups), findAll);
|
|
1820 |
0
| for (Type tSup : IterUtil.skipFirst(sups)) {
|
|
1821 |
0
| PredicateSet<T> forSup = find(tSup, findAll);
|
|
1822 |
0
| result = CollectUtil.intersection(result, forSup);
|
|
1823 |
| |
|
1824 |
| } |
|
1825 |
0
| return result;
|
|
1826 |
| } |
|
1827 |
| } |
|
1828 |
| |
|
1829 |
| }); |
|
1830 |
2201
| PredicateSet<T> result = CollectUtil.union(childMatches, CollectUtil.filter(fromSupers, new Predicate<T>() {
|
|
1831 |
767
| public boolean contains(T match) { return inherits(t, childMatches, match); }
|
|
1832 |
| })); |
|
1833 |
| |
|
1834 |
2201
| return CollectUtil.makeSet(result);
|
|
1835 |
| } |
|
1836 |
| |
|
1837 |
2633
| } finally { debug.logEnd(); }
|
|
1838 |
| } |
|
1839 |
| } |
|
1840 |
| |
|
1841 |
| private class MethodFinder extends MemberFinder<DJMethod> { |
|
1842 |
| private final String _name; |
|
1843 |
| private final Access.Module _accessModule; |
|
1844 |
| private final boolean _onlyStatic; |
|
1845 |
286
| protected MethodFinder(String name, Access.Module accessModule, boolean onlyStatic) {
|
|
1846 |
286
| _name = name;
|
|
1847 |
286
| _accessModule = accessModule;
|
|
1848 |
286
| _onlyStatic = onlyStatic;
|
|
1849 |
| } |
|
1850 |
| |
|
1851 |
| |
|
1852 |
286
| public FunctionInvocationCandidate<DJMethod>
|
|
1853 |
| findSingleMethod(Type t, Iterable<? extends Type> targs, Iterable<? extends Expression> args, |
|
1854 |
| Option<Type> expected) throws UnmatchedLookupException { |
|
1855 |
286
| debug.logStart(new String[]{"t","name","onlyStatic"}, wrap(t), _name, _onlyStatic); try {
|
|
1856 |
| |
|
1857 |
286
| PredicateSet<DJMethod> candidates = findAll(t);
|
|
1858 |
286
| Iterable<FunctionInvocationCandidate<DJMethod>> best = bestInvocations(candidates, targs, args, expected);
|
|
1859 |
| |
|
1860 |
286
| int matches = IterUtil.sizeOf(best);
|
|
1861 |
16
| if (matches == 0) { throw new UnmatchedFunctionLookupException(candidates); }
|
|
1862 |
270
| else if (matches > 1) {
|
|
1863 |
0
| Iterable<DJMethod> ms = IterUtil.map(best, new Lambda<FunctionInvocationCandidate<DJMethod>, DJMethod>() {
|
|
1864 |
0
| public DJMethod value(FunctionInvocationCandidate<DJMethod> c) { return c.function(); }
|
|
1865 |
| }); |
|
1866 |
0
| throw new AmbiguousFunctionLookupException(ms);
|
|
1867 |
| } |
|
1868 |
270
| else { return IterUtil.first(best); }
|
|
1869 |
| |
|
1870 |
286
| } finally { debug.logEnd(); }
|
|
1871 |
| } |
|
1872 |
| |
|
1873 |
942
| protected Iterable<DJMethod> declaredMatches(Type t) {
|
|
1874 |
942
| return t.apply(new TypeAbstractVisitor<Iterable<DJMethod>>() {
|
|
1875 |
9217
| private boolean matches(DJMethod m) {
|
|
1876 |
9217
| return m.declaredName().equals(_name) && !(_onlyStatic && !m.isStatic()) && accessible(m, _accessModule);
|
|
1877 |
| } |
|
1878 |
74
| @Override public Iterable<DJMethod> defaultCase(Type t) { return IterUtil.empty(); }
|
|
1879 |
0
| @Override public Iterable<DJMethod> forArrayType(ArrayType t) {
|
|
1880 |
0
| if (_name.equals("clone") && !_onlyStatic) {
|
|
1881 |
0
| return IterUtil.<DJMethod>make(new ArrayCloneMethod(t));
|
|
1882 |
| } |
|
1883 |
0
| else { return IterUtil.empty(); }
|
|
1884 |
| } |
|
1885 |
868
| @Override public Iterable<DJMethod> forClassType(ClassType t) {
|
|
1886 |
868
| List<DJMethod> result = new LinkedList<DJMethod>();
|
|
1887 |
868
| for (DJMethod m : t.ofClass().declaredMethods()) {
|
|
1888 |
438
| if (matches(m)) { result.add(instantiateMethod(m, t)); }
|
|
1889 |
| } |
|
1890 |
868
| if (!_onlyStatic && _name.equals("getClass")) {
|
|
1891 |
| |
|
1892 |
0
| Iterator<DJMethod> i = result.iterator();
|
|
1893 |
0
| while (i.hasNext()) {
|
|
1894 |
0
| DJMethod m = i.next();
|
|
1895 |
0
| if (!m.isStatic() && m.declaredName().equals("getClass") &&
|
|
1896 |
| OBJECT.ofClass().equals(m.declaringClass()) && IterUtil.isEmpty(m.parameters())) { |
|
1897 |
0
| i.remove();
|
|
1898 |
0
| break;
|
|
1899 |
| } |
|
1900 |
| } |
|
1901 |
0
| result.add(new GetClassMethod(t, StandardTypeSystem.this));
|
|
1902 |
| } |
|
1903 |
868
| return result;
|
|
1904 |
| } |
|
1905 |
| }); |
|
1906 |
| } |
|
1907 |
| |
|
1908 |
767
| protected boolean inherits(Type child, PredicateSet<DJMethod> childMatches, DJMethod match) {
|
|
1909 |
| |
|
1910 |
0
| if (match.accessibility().equals(Access.PRIVATE)) { return false; }
|
|
1911 |
| else { |
|
1912 |
767
| for (DJMethod childMethod : childMatches) {
|
|
1913 |
216
| if (overrides(childMethod, match)) { return false; }
|
|
1914 |
| } |
|
1915 |
551
| return true;
|
|
1916 |
| } |
|
1917 |
| } |
|
1918 |
| |
|
1919 |
| |
|
1920 |
216
| private boolean overrides(DJMethod child, DJMethod parent) {
|
|
1921 |
216
| if (child.declaredName().equals(parent.declaredName())) {
|
|
1922 |
216
| Iterable<Type> subParams = SymbolUtil.parameterTypes(child);
|
|
1923 |
216
| Iterable<Type> supParams = SymbolUtil.parameterTypes(parent);
|
|
1924 |
216
| Iterable<VariableType> subTParams = child.typeParameters();
|
|
1925 |
216
| Iterable<VariableType> supTParams = parent.typeParameters();
|
|
1926 |
216
| if (IterUtil.sizeOf(subParams) == IterUtil.sizeOf(supParams)) {
|
|
1927 |
216
| Iterable<? extends Type> supParamsToCompare;
|
|
1928 |
216
| if (IterUtil.isEmpty(subTParams) && !IterUtil.isEmpty(supTParams)) {
|
|
1929 |
0
| supParamsToCompare = IterUtil.map(supParams, ERASE);
|
|
1930 |
| } |
|
1931 |
216
| else if (IterUtil.sizeOf(subTParams) == IterUtil.sizeOf(supTParams)) {
|
|
1932 |
216
| supParamsToCompare = substitute(supParams, supTParams, subTParams);
|
|
1933 |
| } |
|
1934 |
0
| else { return false; }
|
|
1935 |
216
| for (Pair<Type, Type> p : IterUtil.zip(subParams, supParamsToCompare)) {
|
|
1936 |
0
| if (!isEqual(p.first(), p.second())) { return false; }
|
|
1937 |
| } |
|
1938 |
216
| return true;
|
|
1939 |
| } |
|
1940 |
0
| else { return false; }
|
|
1941 |
| } |
|
1942 |
0
| else { return false; }
|
|
1943 |
| } |
|
1944 |
| |
|
1945 |
| } |
|
1946 |
| |
|
1947 |
| private abstract class FieldFinder<T extends FieldReference> extends MemberFinder<T> { |
|
1948 |
| private final String _name; |
|
1949 |
| private final Access.Module _accessModule; |
|
1950 |
| private final boolean _onlyStatic; |
|
1951 |
438
| protected FieldFinder(String name, Access.Module accessModule, boolean onlyStatic) {
|
|
1952 |
438
| _name = name;
|
|
1953 |
438
| _accessModule = accessModule;
|
|
1954 |
438
| _onlyStatic = onlyStatic;
|
|
1955 |
| } |
|
1956 |
| |
|
1957 |
| |
|
1958 |
178
| public T findSingleField(Type t) throws UnmatchedLookupException {
|
|
1959 |
178
| debug.logStart(new String[]{"t","name","onlyStatic"}, wrap(t), _name, _onlyStatic); try {
|
|
1960 |
| |
|
1961 |
178
| Iterable<T> results = findFirst(t);
|
|
1962 |
| |
|
1963 |
178
| int matches = IterUtil.sizeOf(results);
|
|
1964 |
0
| if (matches != 1) { throw new UnmatchedLookupException(matches); }
|
|
1965 |
178
| else { return IterUtil.first(results); }
|
|
1966 |
| |
|
1967 |
178
| } finally { debug.logEnd(); }
|
|
1968 |
| } |
|
1969 |
| |
|
1970 |
| protected abstract T makeFieldReference(Type declaringType, DJField field); |
|
1971 |
| |
|
1972 |
444
| protected Iterable<T> declaredMatches(Type t) {
|
|
1973 |
444
| Iterable<T> result = t.apply(new TypeAbstractVisitor<Iterable<T>>() {
|
|
1974 |
326
| private boolean matches(DJField f) {
|
|
1975 |
326
| return f.declaredName().equals(_name) && !(_onlyStatic && !f.isStatic()) && accessible(f, _accessModule);
|
|
1976 |
| } |
|
1977 |
0
| @Override public Iterable<T> defaultCase(Type t) { return IterUtil.empty(); }
|
|
1978 |
108
| @Override public Iterable<T> forArrayType(ArrayType t) {
|
|
1979 |
108
| if (_name.equals("length") && !_onlyStatic) {
|
|
1980 |
108
| return IterUtil.make(makeFieldReference(t, ArrayLengthField.INSTANCE));
|
|
1981 |
| } |
|
1982 |
0
| else { return IterUtil.empty(); }
|
|
1983 |
| } |
|
1984 |
336
| @Override public Iterable<T> forClassType(ClassType t) {
|
|
1985 |
336
| for (DJField f : t.ofClass().declaredFields()) {
|
|
1986 |
324
| if (matches(f)) { return IterUtil.make(makeFieldReference(t, f)); }
|
|
1987 |
| } |
|
1988 |
12
| return IterUtil.empty();
|
|
1989 |
| } |
|
1990 |
| }); |
|
1991 |
444
| return result;
|
|
1992 |
| } |
|
1993 |
| |
|
1994 |
0
| protected boolean inherits(Type child, PredicateSet<T> childMatches, T match) {
|
|
1995 |
| |
|
1996 |
0
| return childMatches.isEmpty() && !match.field().accessibility().equals(Access.PRIVATE);
|
|
1997 |
| } |
|
1998 |
| |
|
1999 |
| } |
|
2000 |
| |
|
2001 |
| private class ClassFinder extends MemberFinder<ClassType> { |
|
2002 |
| private final String _name; |
|
2003 |
| private final Iterable<? extends Type> _typeArgs; |
|
2004 |
| private final Access.Module _accessModule; |
|
2005 |
| private final boolean _onlyStatic; |
|
2006 |
524
| protected ClassFinder(String name, Iterable<? extends Type> typeArgs, Access.Module accessModule,
|
|
2007 |
| boolean onlyStatic) { |
|
2008 |
524
| _name = name;
|
|
2009 |
524
| _typeArgs = typeArgs;
|
|
2010 |
524
| _accessModule = accessModule;
|
|
2011 |
524
| _onlyStatic = onlyStatic;
|
|
2012 |
| } |
|
2013 |
| |
|
2014 |
| |
|
2015 |
| |
|
2016 |
| |
|
2017 |
| |
|
2018 |
0
| public ClassType findSingleClass(Type t) throws InvalidTypeArgumentException, UnmatchedLookupException {
|
|
2019 |
0
| debug.logStart(new String[]{"t","name","typeArgs", "onlyStatic"},
|
|
2020 |
0
| wrap(t), _name, wrap(_typeArgs), _onlyStatic); try {
|
|
2021 |
| |
|
2022 |
0
| Iterable<ClassType> results = findFirst(t);
|
|
2023 |
| |
|
2024 |
0
| int matches = IterUtil.sizeOf(results);
|
|
2025 |
0
| if (matches != 1) { throw new UnmatchedLookupException(matches); }
|
|
2026 |
| else { |
|
2027 |
0
| ClassType result = IterUtil.first(results);
|
|
2028 |
0
| final Iterable<VariableType> params = SymbolUtil.allTypeParameters(result.ofClass());
|
|
2029 |
0
| try {
|
|
2030 |
0
| return result.apply(new TypeAbstractVisitor<ClassType>() {
|
|
2031 |
0
| public ClassType defaultCase(Type t) { throw new IllegalArgumentException(); }
|
|
2032 |
| |
|
2033 |
0
| @Override public ClassType forSimpleClassType(SimpleClassType t) {
|
|
2034 |
0
| if (IterUtil.isEmpty(params)) { return t; }
|
|
2035 |
0
| else { return new RawClassType(t.ofClass()); }
|
|
2036 |
| } |
|
2037 |
| |
|
2038 |
0
| @Override public ClassType forRawClassType(RawClassType t) {
|
|
2039 |
0
| return t;
|
|
2040 |
| } |
|
2041 |
| |
|
2042 |
0
| @Override public ClassType forParameterizedClassType(ParameterizedClassType t) {
|
|
2043 |
0
| try {
|
|
2044 |
0
| if (IterUtil.sizeOf(params) != IterUtil.sizeOf(t.typeArguments())) {
|
|
2045 |
0
| throw new InvalidTypeArgumentException();
|
|
2046 |
| } |
|
2047 |
0
| return t;
|
|
2048 |
| } |
|
2049 |
0
| catch (InvalidTypeArgumentException e) { throw new WrappedException(e); }
|
|
2050 |
| } |
|
2051 |
| }); |
|
2052 |
| } |
|
2053 |
| catch (WrappedException e) { |
|
2054 |
0
| if (e.getCause() instanceof InvalidTypeArgumentException) {
|
|
2055 |
0
| throw (InvalidTypeArgumentException) e.getCause();
|
|
2056 |
| } |
|
2057 |
0
| else { throw e; }
|
|
2058 |
| } |
|
2059 |
| } |
|
2060 |
| |
|
2061 |
0
| } finally { debug.logEnd(); }
|
|
2062 |
| } |
|
2063 |
| |
|
2064 |
| |
|
2065 |
| |
|
2066 |
| |
|
2067 |
| |
|
2068 |
| |
|
2069 |
| |
|
2070 |
1247
| protected Iterable<ClassType> declaredMatches(Type t) {
|
|
2071 |
1247
| return t.apply(new TypeAbstractVisitor<Iterable<ClassType>>() {
|
|
2072 |
| |
|
2073 |
28
| @Override public Iterable<ClassType> defaultCase(Type t) { return IterUtil.empty(); }
|
|
2074 |
| |
|
2075 |
1219
| @Override public Iterable<ClassType> forClassType(final ClassType t) {
|
|
2076 |
| |
|
2077 |
1219
| Predicate<DJClass> matchInner = new Predicate<DJClass>() {
|
|
2078 |
0
| public boolean contains(DJClass c) {
|
|
2079 |
0
| return !c.isAnonymous() && c.declaredName().equals(_name) && !(_onlyStatic && !c.isStatic()) &&
|
|
2080 |
| accessible(c, _accessModule); |
|
2081 |
| } |
|
2082 |
| }; |
|
2083 |
1219
| Lambda<DJClass, ClassType> makeType = new Lambda<DJClass, ClassType>() {
|
|
2084 |
0
| public ClassType value(DJClass c) {
|
|
2085 |
0
| ClassType dynamicOuter;
|
|
2086 |
0
| if (c.isStatic()) { dynamicOuter = SymbolUtil.dynamicOuterClassType(t); }
|
|
2087 |
0
| else { dynamicOuter = t; }
|
|
2088 |
0
| if (dynamicOuter instanceof ParameterizedClassType) {
|
|
2089 |
0
| Iterable<? extends Type> outerTypeArgs = ((ParameterizedClassType) dynamicOuter).typeArguments();
|
|
2090 |
0
| return new ParameterizedClassType(c, IterUtil.compose(outerTypeArgs, _typeArgs));
|
|
2091 |
| } |
|
2092 |
0
| else if (dynamicOuter instanceof RawClassType) {
|
|
2093 |
| |
|
2094 |
0
| return IterUtil.isEmpty(_typeArgs) ? new RawClassType(c) : new ParameterizedClassType(c, _typeArgs);
|
|
2095 |
| } |
|
2096 |
| else { |
|
2097 |
0
| return IterUtil.isEmpty(_typeArgs) ? new SimpleClassType(c) : new ParameterizedClassType(c, _typeArgs);
|
|
2098 |
| } |
|
2099 |
| } |
|
2100 |
| }; |
|
2101 |
1219
| return IterUtil.map(IterUtil.filter(t.ofClass().declaredClasses(), matchInner), makeType);
|
|
2102 |
| } |
|
2103 |
| |
|
2104 |
| }); |
|
2105 |
| } |
|
2106 |
| |
|
2107 |
0
| protected boolean inherits(Type child, PredicateSet<ClassType> childMatches, ClassType match) {
|
|
2108 |
| |
|
2109 |
0
| return childMatches.isEmpty() && !match.ofClass().accessibility().equals(Access.PRIVATE);
|
|
2110 |
| } |
|
2111 |
| |
|
2112 |
| } |
|
2113 |
| |
|
2114 |
| private class FunctionInvocationCandidate<F extends Function> { |
|
2115 |
| private final F _f; |
|
2116 |
| private final SignatureMatcher _matcher; |
|
2117 |
| |
|
2118 |
1546
| public FunctionInvocationCandidate(F f, Iterable<? extends Type> targs,
|
|
2119 |
| Iterable<? extends Expression> args, Option<Type> expected) { |
|
2120 |
1546
| _f = f;
|
|
2121 |
1546
| _matcher = makeMatcher(f.typeParameters(), targs, SymbolUtil.parameterTypes(f), args, f.returnType(), expected);
|
|
2122 |
| } |
|
2123 |
| |
|
2124 |
821
| public F function() { return _f; }
|
|
2125 |
821
| public Iterable<? extends Type> typeArguments() { return _matcher.typeArguments(); }
|
|
2126 |
821
| public Iterable<? extends Expression> arguments() { return _matcher.arguments(); }
|
|
2127 |
| |
|
2128 |
821
| public SubstitutionMap substitution() {
|
|
2129 |
821
| return new SubstitutionMap(_f.typeParameters(), _matcher.typeArguments());
|
|
2130 |
| } |
|
2131 |
| |
|
2132 |
1556
| private SignatureMatcher makeMatcher(Iterable<? extends VariableType> tparams,
|
|
2133 |
| Iterable<? extends Type> targs, |
|
2134 |
| Iterable<? extends Type> params, |
|
2135 |
| Iterable<? extends Expression> args, |
|
2136 |
| Type returned, Option<Type> expected) { |
|
2137 |
| |
|
2138 |
1556
| int argCount = IterUtil.sizeOf(args);
|
|
2139 |
1556
| int paramCount = IterUtil.sizeOf(params);
|
|
2140 |
1556
| if (argCount == paramCount - 1) {
|
|
2141 |
216
| if (IterUtil.isEmpty(tparams)) {
|
|
2142 |
216
| return new EmptyVarargMatcher(params, args, tparams, EMPTY_TYPE_ITERABLE);
|
|
2143 |
| } |
|
2144 |
0
| else if (IterUtil.isEmpty(targs) || !_useExplicitTypeArgs) {
|
|
2145 |
0
| return new EmptyVarargInferenceMatcher(params, args, tparams, returned, expected);
|
|
2146 |
| } |
|
2147 |
0
| else if (IterUtil.sizeOf(tparams) == IterUtil.sizeOf(targs) && inBounds(tparams, targs)) {
|
|
2148 |
0
| return new EmptyVarargMatcher(substitute(params, tparams, targs), args, tparams, targs);
|
|
2149 |
| } |
|
2150 |
0
| else { return NullMatcher.INSTANCE; }
|
|
2151 |
| } |
|
2152 |
1340
| else if (argCount == paramCount) {
|
|
2153 |
1141
| if (IterUtil.isEmpty(tparams)) {
|
|
2154 |
1116
| return new SimpleMatcher(params, args, tparams, EMPTY_TYPE_ITERABLE);
|
|
2155 |
| } |
|
2156 |
25
| else if (IterUtil.isEmpty(targs) || !_useExplicitTypeArgs) {
|
|
2157 |
25
| return new InferenceMatcher(params, args, tparams, returned, expected);
|
|
2158 |
| } |
|
2159 |
0
| else if (IterUtil.sizeOf(tparams) == IterUtil.sizeOf(targs) && inBounds(tparams, targs)) {
|
|
2160 |
0
| return new SimpleMatcher(substitute(params, tparams, targs), args, tparams, targs);
|
|
2161 |
| } |
|
2162 |
0
| else { return NullMatcher.INSTANCE; }
|
|
2163 |
| } |
|
2164 |
199
| else if (argCount > paramCount && paramCount >= 1) {
|
|
2165 |
12
| if (IterUtil.isEmpty(tparams)) {
|
|
2166 |
12
| return new MultiVarargMatcher(params, args, tparams, EMPTY_TYPE_ITERABLE);
|
|
2167 |
| } |
|
2168 |
0
| else if (IterUtil.isEmpty(targs) || !_useExplicitTypeArgs) {
|
|
2169 |
0
| return new MultiVarargInferenceMatcher(params, args, tparams, returned, expected);
|
|
2170 |
| } |
|
2171 |
0
| else if (IterUtil.sizeOf(tparams) == IterUtil.sizeOf(targs) && inBounds(tparams, targs)) {
|
|
2172 |
0
| return new MultiVarargMatcher(substitute(params, tparams, targs), args, tparams, targs);
|
|
2173 |
| } |
|
2174 |
0
| else { return NullMatcher.INSTANCE; }
|
|
2175 |
| } |
|
2176 |
187
| else { return NullMatcher.INSTANCE; }
|
|
2177 |
| } |
|
2178 |
| |
|
2179 |
| |
|
2180 |
| |
|
2181 |
| |
|
2182 |
| |
|
2183 |
10
| public boolean moreSpecificThan(FunctionInvocationCandidate<F> c) {
|
|
2184 |
10
| Iterable<Type> supParams = SymbolUtil.parameterTypes(c._f);
|
|
2185 |
10
| Iterable<Type> subParams = SymbolUtil.parameterTypes(_f);
|
|
2186 |
10
| if (SymbolUtil.isVararg(c._f)) {
|
|
2187 |
| |
|
2188 |
| |
|
2189 |
0
| int supArity = IterUtil.sizeOf(supParams);
|
|
2190 |
0
| int subArity = IterUtil.sizeOf(subParams);
|
|
2191 |
0
| if (SymbolUtil.isVararg(_f)) {
|
|
2192 |
0
| if (subArity < supArity) {
|
|
2193 |
0
| Iterable<Type> prefixSubs = IterUtil.skipLast(subParams);
|
|
2194 |
0
| Type lastSub = IterUtil.last(subParams);
|
|
2195 |
0
| Iterable<Type> subExtras = IterUtil.copy(((ArrayType) lastSub).ofType(), supArity-subArity);
|
|
2196 |
0
| subParams = IterUtil.compose(IterUtil.compose(prefixSubs, subExtras), lastSub);
|
|
2197 |
| } |
|
2198 |
0
| else if (subArity > supArity) {
|
|
2199 |
0
| Iterable<Type> prefixSups = IterUtil.skipLast(supParams);
|
|
2200 |
0
| Type lastSup = IterUtil.last(supParams);
|
|
2201 |
0
| Iterable<Type> supExtras = IterUtil.copy(((ArrayType) lastSup).ofType(), subArity-supArity);
|
|
2202 |
0
| supParams = IterUtil.compose(IterUtil.compose(prefixSups, supExtras), lastSup);
|
|
2203 |
| } |
|
2204 |
| |
|
2205 |
| } |
|
2206 |
| else { |
|
2207 |
| |
|
2208 |
| |
|
2209 |
0
| if (subArity < supArity) { supParams = IterUtil.skipLast(supParams); }
|
|
2210 |
0
| else if (subArity > supArity) {
|
|
2211 |
0
| Iterable<Type> prefixSups = IterUtil.skipLast(supParams);
|
|
2212 |
0
| Type lastSup = IterUtil.last(supParams);
|
|
2213 |
0
| int varargArgs = subArity-(supArity-1);
|
|
2214 |
0
| supParams = IterUtil.compose(prefixSups, IterUtil.copy(((ArrayType) lastSup).ofType(), varargArgs));
|
|
2215 |
| } |
|
2216 |
| |
|
2217 |
| |
|
2218 |
| |
|
2219 |
| } |
|
2220 |
| } |
|
2221 |
10
| SignatureMatcher m = makeMatcher(c._f.typeParameters(), EMPTY_TYPE_ITERABLE, supParams,
|
|
2222 |
| IterUtil.mapSnapshot(subParams, EMPTY_EXPRESSION_FOR_TYPE), |
|
2223 |
| BOTTOM, NONE_TYPE_OPTION); |
|
2224 |
10
| return m.matches() || _boxingInMostSpecific && m.matchesWithBoxing();
|
|
2225 |
| } |
|
2226 |
| |
|
2227 |
| } |
|
2228 |
| |
|
2229 |
| |
|
2230 |
| |
|
2231 |
| |
|
2232 |
| |
|
2233 |
| |
|
2234 |
838
| private <F extends Function>
|
|
2235 |
| Iterable<FunctionInvocationCandidate<F>> bestInvocations(Iterable<F> functions, |
|
2236 |
| final Iterable<? extends Type> targs, |
|
2237 |
| final Iterable<? extends Expression> args, |
|
2238 |
| final Option<Type> expected) { |
|
2239 |
| |
|
2240 |
| |
|
2241 |
838
| Iterable<FunctionInvocationCandidate<F>> candidates = IterUtil.mapSnapshot(functions,
|
|
2242 |
| new Lambda<F, FunctionInvocationCandidate<F>>() { |
|
2243 |
1546
| public FunctionInvocationCandidate<F> value(F f) {
|
|
2244 |
1546
| return new FunctionInvocationCandidate<F>(f, targs, args, expected);
|
|
2245 |
| } |
|
2246 |
| }); |
|
2247 |
838
| List<FunctionInvocationCandidate<F>> matches = new LinkedList<FunctionInvocationCandidate<F>>();
|
|
2248 |
838
| for (FunctionInvocationCandidate<F> c : candidates) {
|
|
2249 |
811
| if (c._matcher.matches()) { matches.add(c); }
|
|
2250 |
| } |
|
2251 |
838
| if (matches.isEmpty()) {
|
|
2252 |
37
| for (FunctionInvocationCandidate<F> c : candidates) {
|
|
2253 |
0
| if (c._matcher.matchesWithBoxing()) { matches.add(c); }
|
|
2254 |
| } |
|
2255 |
| } |
|
2256 |
838
| if (matches.isEmpty()) {
|
|
2257 |
37
| for (FunctionInvocationCandidate<F> c : candidates) {
|
|
2258 |
20
| if (c._matcher.matchesWithVarargs()) { matches.add(c); }
|
|
2259 |
| } |
|
2260 |
| } |
|
2261 |
838
| return CollectUtil.minList(matches, new Order<FunctionInvocationCandidate<F>>() {
|
|
2262 |
10
| public boolean contains(FunctionInvocationCandidate<F> c1, FunctionInvocationCandidate<F> c2) {
|
|
2263 |
10
| return c1.moreSpecificThan(c2);
|
|
2264 |
| } |
|
2265 |
| }); |
|
2266 |
| } |
|
2267 |
| |
|
2268 |
| private static final Lambda<Type, Expression> EMPTY_EXPRESSION_FOR_TYPE = new Lambda<Type, Expression>() { |
|
2269 |
19
| public Expression value(Type t) {
|
|
2270 |
19
| Expression result = TypeUtil.makeEmptyExpression();
|
|
2271 |
19
| NodeProperties.setType(result, t);
|
|
2272 |
19
| return result;
|
|
2273 |
| } |
|
2274 |
| }; |
|
2275 |
| |
|
2276 |
| |
|
2277 |
| |
|
2278 |
| |
|
2279 |
| |
|
2280 |
438
| private DJMethod instantiateMethod(final DJMethod declaredMethod, Type declaringType) {
|
|
2281 |
438
| Type dynamicContext;
|
|
2282 |
438
| if (declaredMethod.isStatic()) {
|
|
2283 |
216
| if (declaringType instanceof ClassType) {
|
|
2284 |
216
| dynamicContext = SymbolUtil.dynamicOuterClassType((ClassType) declaringType);
|
|
2285 |
| } |
|
2286 |
0
| else { dynamicContext = null; }
|
|
2287 |
| } |
|
2288 |
222
| else { dynamicContext = declaringType; }
|
|
2289 |
216
| if (dynamicContext == null) { return declaredMethod; }
|
|
2290 |
| else { |
|
2291 |
222
| return dynamicContext.apply(new TypeAbstractVisitor<DJMethod>() {
|
|
2292 |
153
| @Override public DJMethod defaultCase(Type dynamicContext) { return declaredMethod; }
|
|
2293 |
0
| @Override public DJMethod forRawClassType(RawClassType dynamicContext) {
|
|
2294 |
| |
|
2295 |
0
| return new ErasedMethod(declaredMethod);
|
|
2296 |
| } |
|
2297 |
69
| @Override public DJMethod forParameterizedClassType(ParameterizedClassType dynamicContext) {
|
|
2298 |
69
| ParameterizedClassType dynamicContextCap = capture(dynamicContext);
|
|
2299 |
69
| Iterable<VariableType> tparams = SymbolUtil.allTypeParameters(dynamicContextCap.ofClass());
|
|
2300 |
69
| return new InstantiatedMethod(declaredMethod, tparams, dynamicContextCap.typeArguments());
|
|
2301 |
| } |
|
2302 |
| }); |
|
2303 |
| } |
|
2304 |
| } |
|
2305 |
| |
|
2306 |
| private static abstract class DelegatingFunction<T extends Function> implements Function { |
|
2307 |
| protected final T _delegate; |
|
2308 |
289
| protected DelegatingFunction(T delegate) { _delegate = delegate; }
|
|
2309 |
| |
|
2310 |
57
| public String declaredName() { return _delegate.declaredName(); }
|
|
2311 |
333
| public Iterable<LocalVariable> parameters() {
|
|
2312 |
333
| return IterUtil.mapSnapshot(IterUtil.zip(_delegate.parameters(), parameterTypes()),
|
|
2313 |
| new Lambda<Pair<LocalVariable, Type>, LocalVariable>() { |
|
2314 |
289
| public LocalVariable value(Pair<LocalVariable, Type> p) {
|
|
2315 |
289
| return new LocalVariable(p.first().declaredName(), p.second(), p.first().isFinal());
|
|
2316 |
| } |
|
2317 |
| }); |
|
2318 |
| } |
|
2319 |
| |
|
2320 |
| public abstract Iterable<VariableType> typeParameters(); |
|
2321 |
| public abstract Type returnType(); |
|
2322 |
| public abstract Iterable<Type> thrownTypes(); |
|
2323 |
| protected abstract Iterable<? extends Type> parameterTypes(); |
|
2324 |
| } |
|
2325 |
| |
|
2326 |
| private static abstract class DelegatingMethod extends DelegatingFunction<DJMethod> implements DJMethod { |
|
2327 |
69
| protected DelegatingMethod(DJMethod delegate) { super(delegate); }
|
|
2328 |
0
| public DJClass declaringClass() { return _delegate.declaringClass(); }
|
|
2329 |
0
| public boolean isStatic() { return _delegate.isStatic(); }
|
|
2330 |
0
| public boolean isAbstract() { return _delegate.isAbstract(); }
|
|
2331 |
0
| public boolean isFinal() { return _delegate.isFinal(); }
|
|
2332 |
47
| public Access accessibility() { return _delegate.accessibility(); }
|
|
2333 |
0
| public Access.Module accessModule() { return _delegate.accessModule(); }
|
|
2334 |
0
| public DJMethod declaredSignature() { return _delegate.declaredSignature(); }
|
|
2335 |
34
| public Object evaluate(Object receiver, Iterable<Object> args, RuntimeBindings bindings, Options options)
|
|
2336 |
| throws EvaluatorException { |
|
2337 |
34
| return _delegate.evaluate(receiver, args, bindings, options);
|
|
2338 |
| } |
|
2339 |
| } |
|
2340 |
| |
|
2341 |
| private class ErasedMethod extends DelegatingMethod { |
|
2342 |
0
| public ErasedMethod(DJMethod m) { super(m); }
|
|
2343 |
0
| public Iterable<VariableType> typeParameters() { return IterUtil.empty(); }
|
|
2344 |
0
| public Type returnType() { return erase(_delegate.returnType()); }
|
|
2345 |
0
| public Iterable<Type> thrownTypes() { return IterUtil.mapSnapshot(_delegate.thrownTypes(), ERASE); }
|
|
2346 |
0
| protected Iterable<Type> parameterTypes() {
|
|
2347 |
0
| return IterUtil.mapSnapshot(SymbolUtil.parameterTypes(_delegate), ERASE);
|
|
2348 |
| } |
|
2349 |
| } |
|
2350 |
| |
|
2351 |
| private class InstantiatedMethod extends DelegatingMethod { |
|
2352 |
| private final SubstitutionMap _sigma; |
|
2353 |
| private final Iterable<VariableType> _tparams; |
|
2354 |
69
| public InstantiatedMethod(DJMethod m, Iterable<VariableType> classTParams, Iterable<? extends Type> classTArgs) {
|
|
2355 |
69
| super(m);
|
|
2356 |
69
| Pair<Iterable<VariableType>, SubstitutionMap> p = instantiateTypeParameters(m, classTParams, classTArgs);
|
|
2357 |
69
| _tparams = p.first();
|
|
2358 |
69
| _sigma = p.second();
|
|
2359 |
| } |
|
2360 |
| |
|
2361 |
143
| public Type returnType() { return substitute(_delegate.returnType(), _sigma); }
|
|
2362 |
155
| public Iterable<VariableType> typeParameters() { return _tparams; }
|
|
2363 |
43
| public Iterable<Type> thrownTypes() { return IterUtil.relax(substitute(_delegate.thrownTypes(), _sigma)); }
|
|
2364 |
112
| public Iterable<? extends Type> parameterTypes() {
|
|
2365 |
112
| return substitute(SymbolUtil.parameterTypes(_delegate), _sigma);
|
|
2366 |
| } |
|
2367 |
0
| public String toString() {
|
|
2368 |
0
| TypePrinter p = typePrinter();
|
|
2369 |
0
| return "InstantiatedMethod(" + p.print(this) + ")";
|
|
2370 |
| } |
|
2371 |
| } |
|
2372 |
| |
|
2373 |
| private static abstract class DelegatingConstructor extends DelegatingFunction<DJConstructor> |
|
2374 |
| implements DJConstructor { |
|
2375 |
220
| protected DelegatingConstructor(DJConstructor delegate) { super(delegate); }
|
|
2376 |
0
| public DJClass declaringClass() { return _delegate.declaringClass(); }
|
|
2377 |
220
| public Type returnType() { return _delegate.returnType(); }
|
|
2378 |
266
| public Access accessibility() { return _delegate.accessibility(); }
|
|
2379 |
0
| public Access.Module accessModule() { return _delegate.accessModule(); }
|
|
2380 |
7
| public DJConstructor declaredSignature() { return _delegate.declaredSignature(); }
|
|
2381 |
71
| public Object evaluate(Object outer, Iterable<Object> args, RuntimeBindings bindings, Options options)
|
|
2382 |
| throws EvaluatorException { |
|
2383 |
71
| return _delegate.evaluate(outer, args, bindings, options);
|
|
2384 |
| } |
|
2385 |
| } |
|
2386 |
| |
|
2387 |
| private class ErasedConstructor extends DelegatingConstructor { |
|
2388 |
0
| public ErasedConstructor(DJConstructor k) { super(k); }
|
|
2389 |
0
| public Iterable<VariableType> typeParameters() { return IterUtil.empty(); }
|
|
2390 |
0
| public Iterable<Type> thrownTypes() { return IterUtil.mapSnapshot(_delegate.thrownTypes(), ERASE); }
|
|
2391 |
0
| protected Iterable<Type> parameterTypes() {
|
|
2392 |
0
| return IterUtil.mapSnapshot(SymbolUtil.parameterTypes(_delegate), ERASE);
|
|
2393 |
| } |
|
2394 |
0
| public String toString() { return "ErasedConstructor(" + declaredName() + ")"; }
|
|
2395 |
| } |
|
2396 |
| |
|
2397 |
| private class InstantiatedConstructor extends DelegatingConstructor { |
|
2398 |
| private final SubstitutionMap _sigma; |
|
2399 |
| private final Iterable<VariableType> _tparams; |
|
2400 |
220
| public InstantiatedConstructor(DJConstructor k, Iterable<VariableType> classTParams,
|
|
2401 |
| Iterable<? extends Type> classTArgs) { |
|
2402 |
220
| super(k);
|
|
2403 |
220
| Pair<Iterable<VariableType>, SubstitutionMap> p = instantiateTypeParameters(k, classTParams, classTArgs);
|
|
2404 |
220
| _tparams = p.first();
|
|
2405 |
220
| _sigma = p.second();
|
|
2406 |
| } |
|
2407 |
| |
|
2408 |
433
| public Iterable<VariableType> typeParameters() { return _tparams; }
|
|
2409 |
212
| public Iterable<Type> thrownTypes() { return IterUtil.relax(substitute(_delegate.thrownTypes(), _sigma)); }
|
|
2410 |
221
| public Iterable<? extends Type> parameterTypes() {
|
|
2411 |
221
| return substitute(SymbolUtil.parameterTypes(_delegate), _sigma);
|
|
2412 |
| } |
|
2413 |
0
| public String toString() { return "InstantiatedConstructor(" + declaredName() + ")"; }
|
|
2414 |
| } |
|
2415 |
| |
|
2416 |
| |
|
2417 |
289
| private Pair<Iterable<VariableType>, SubstitutionMap>
|
|
2418 |
| instantiateTypeParameters(Function f, |
|
2419 |
| Iterable<? extends VariableType> enclosingTParams, |
|
2420 |
| Iterable<? extends Type> enclosingTArgs) { |
|
2421 |
289
| Iterable<VariableType> origTParams = f.typeParameters();
|
|
2422 |
289
| Iterable<VariableType> tparams = IterUtil.mapSnapshot(origTParams, new Lambda<VariableType, VariableType>() {
|
|
2423 |
0
| public VariableType value(VariableType var) {
|
|
2424 |
0
| return new VariableType(new BoundedSymbol(new Object(), var.symbol().name()));
|
|
2425 |
| } |
|
2426 |
| }); |
|
2427 |
289
| SubstitutionMap sigma = new SubstitutionMap(IterUtil.compose(enclosingTParams, origTParams),
|
|
2428 |
| IterUtil.compose(enclosingTArgs, tparams)); |
|
2429 |
289
| for (Pair<VariableType, VariableType> p : IterUtil.zip(origTParams, tparams)) {
|
|
2430 |
0
| VariableType origParam = p.first();
|
|
2431 |
0
| VariableType newParam = p.second();
|
|
2432 |
0
| newParam.symbol().initializeUpperBound(substitute(origParam.symbol().upperBound(), sigma));
|
|
2433 |
0
| newParam.symbol().initializeLowerBound(substitute(origParam.symbol().lowerBound(), sigma));
|
|
2434 |
| } |
|
2435 |
289
| return Pair.make(tparams, sigma);
|
|
2436 |
| } |
|
2437 |
| |
|
2438 |
| |
|
2439 |
| |
|
2440 |
| |
|
2441 |
| |
|
2442 |
| |
|
2443 |
| |
|
2444 |
| |
|
2445 |
| private static abstract class SignatureMatcher { |
|
2446 |
| |
|
2447 |
| public abstract boolean matches(); |
|
2448 |
| |
|
2449 |
| |
|
2450 |
| public abstract boolean matchesWithBoxing(); |
|
2451 |
| |
|
2452 |
| |
|
2453 |
| public abstract boolean matchesWithVarargs(); |
|
2454 |
| |
|
2455 |
| |
|
2456 |
| public abstract Iterable<? extends Type> typeArguments(); |
|
2457 |
| |
|
2458 |
| |
|
2459 |
| public abstract Iterable<? extends Expression> arguments(); |
|
2460 |
| } |
|
2461 |
| |
|
2462 |
| private static class NullMatcher extends SignatureMatcher { |
|
2463 |
| public static final NullMatcher INSTANCE = new NullMatcher(); |
|
2464 |
1
| private NullMatcher() {}
|
|
2465 |
187
| public boolean matches() { return false; }
|
|
2466 |
4
| public boolean matchesWithBoxing() { return false; }
|
|
2467 |
4
| public boolean matchesWithVarargs() { return false; }
|
|
2468 |
0
| public Iterable<? extends Type> typeArguments() { throw new IllegalStateException(); }
|
|
2469 |
0
| public Iterable<? extends Expression> arguments() { throw new IllegalStateException(); }
|
|
2470 |
| } |
|
2471 |
| |
|
2472 |
| |
|
2473 |
| private class SimpleMatcher extends SignatureMatcher { |
|
2474 |
| protected Iterable<? extends Type> _params; |
|
2475 |
| protected Iterable<? extends Expression> _args; |
|
2476 |
| protected Iterable<? extends VariableType> _tparams; |
|
2477 |
| protected Iterable<? extends Type> _targs; |
|
2478 |
| protected Type _paramForVarargs; |
|
2479 |
| protected Expression _argForVarargs; |
|
2480 |
| protected boolean _matchesAllButLast; |
|
2481 |
| |
|
2482 |
| |
|
2483 |
1369
| public SimpleMatcher(Iterable<? extends Type> params, Iterable<? extends Expression> args,
|
|
2484 |
| Iterable<? extends VariableType> tparams, Iterable<? extends Type> targs) { |
|
2485 |
1369
| _params = params;
|
|
2486 |
1369
| _args = args;
|
|
2487 |
1369
| _tparams = tparams;
|
|
2488 |
1369
| _targs = targs;
|
|
2489 |
| } |
|
2490 |
| |
|
2491 |
1642
| public Iterable<? extends Type> typeArguments() { return _targs; }
|
|
2492 |
821
| public Iterable<? extends Expression> arguments() { return _args; }
|
|
2493 |
| |
|
2494 |
1135
| public boolean matches() {
|
|
2495 |
1135
| Iterator<? extends Type> pI = _params.iterator();
|
|
2496 |
1135
| Iterator<? extends Expression> aI = _args.iterator();
|
|
2497 |
1135
| while (pI.hasNext()) {
|
|
2498 |
| |
|
2499 |
1062
| if (!isSubtype(NodeProperties.getType(aI.next()), pI.next())) {
|
|
2500 |
321
| _matchesAllButLast = !pI.hasNext();
|
|
2501 |
321
| return false;
|
|
2502 |
| } |
|
2503 |
| } |
|
2504 |
814
| return true;
|
|
2505 |
| } |
|
2506 |
| |
|
2507 |
11
| public boolean matchesWithBoxing() { return boxArgs() && matches(); }
|
|
2508 |
| |
|
2509 |
11
| public boolean matchesWithVarargs() {
|
|
2510 |
11
| if (_matchesAllButLast && _paramForVarargs instanceof VarargArrayType) {
|
|
2511 |
4
| ArrayType arrayT = (ArrayType) substitute(_paramForVarargs, _tparams, _targs);
|
|
2512 |
4
| Type elementT = arrayT.ofType();
|
|
2513 |
4
| _argForVarargs = boxingConvert(_argForVarargs, elementT);
|
|
2514 |
| |
|
2515 |
4
| if (isSubtype(NodeProperties.getType(_argForVarargs), elementT)) {
|
|
2516 |
4
| Expression newArg = makeArray(arrayT, IterUtil.make(_argForVarargs));
|
|
2517 |
4
| _args = IterUtil.compose(IterUtil.skipLast(_args), newArg);
|
|
2518 |
4
| return true;
|
|
2519 |
| } |
|
2520 |
| } |
|
2521 |
7
| return false;
|
|
2522 |
| } |
|
2523 |
| |
|
2524 |
| |
|
2525 |
| |
|
2526 |
| |
|
2527 |
| |
|
2528 |
| |
|
2529 |
| |
|
2530 |
29
| protected boolean boxArgs() {
|
|
2531 |
29
| Iterable<Expression> newArgs = EMPTY_EXPRESSION_ITERABLE;
|
|
2532 |
29
| boolean result = false;
|
|
2533 |
29
| Iterator<? extends Type> pI = _params.iterator();
|
|
2534 |
29
| Iterator<? extends Expression> aI = _args.iterator();
|
|
2535 |
29
| while (pI.hasNext()) {
|
|
2536 |
22
| Type pT = pI.next();
|
|
2537 |
22
| Expression aE = aI.next();
|
|
2538 |
21
| if (!pI.hasNext()) { _paramForVarargs = pT; _argForVarargs = aE; }
|
|
2539 |
22
| Expression newArg = boxingConvert(aE, pT);
|
|
2540 |
3
| if (newArg != aE) { result = true; }
|
|
2541 |
22
| newArgs = IterUtil.compose(newArgs, newArg);
|
|
2542 |
| } |
|
2543 |
3
| if (result) { _args = newArgs; }
|
|
2544 |
29
| return result;
|
|
2545 |
| } |
|
2546 |
| |
|
2547 |
| |
|
2548 |
71
| protected Expression boxingConvert(Expression exp, Type target) {
|
|
2549 |
71
| Type t = NodeProperties.getType(exp);
|
|
2550 |
71
| if (isPrimitive(target) && isPrimitiveConvertible(t)) {
|
|
2551 |
16
| try { return makePrimitive(exp); }
|
|
2552 |
0
| catch (UnsupportedConversionException e) { throw new RuntimeException("isPrimitiveConvertible() lied"); }
|
|
2553 |
| } |
|
2554 |
55
| else if (isReference(target) && isReferenceConvertible(t)) {
|
|
2555 |
55
| try { return makeReference(exp); }
|
|
2556 |
0
| catch (UnsupportedConversionException e) { throw new RuntimeException("isReferenceConvertible() lied"); }
|
|
2557 |
| } |
|
2558 |
0
| else { return exp; }
|
|
2559 |
| } |
|
2560 |
| |
|
2561 |
| } |
|
2562 |
| |
|
2563 |
| |
|
2564 |
| private class InferenceMatcher extends SimpleMatcher { |
|
2565 |
| |
|
2566 |
| protected final Type _returned; |
|
2567 |
| protected final Option<Type> _expected; |
|
2568 |
| |
|
2569 |
| |
|
2570 |
25
| public InferenceMatcher(Iterable<? extends Type> params, Iterable<? extends Expression> args,
|
|
2571 |
| Iterable<? extends VariableType> tparams, |
|
2572 |
| Type returned, Option<Type> expected) { |
|
2573 |
25
| super(params, args, tparams, null);
|
|
2574 |
25
| _returned = returned;
|
|
2575 |
25
| if (expected.isSome()) {
|
|
2576 |
25
| Expression exp = TypeUtil.makeEmptyExpression();
|
|
2577 |
25
| NodeProperties.setType(exp, expected.unwrap());
|
|
2578 |
25
| _expected = Option.some(NodeProperties.getType(boxingConvert(exp, _returned)));
|
|
2579 |
| } |
|
2580 |
0
| else { _expected = expected; }
|
|
2581 |
| } |
|
2582 |
| |
|
2583 |
25
| @Override public boolean matches() {
|
|
2584 |
25
| Iterable<Type> argTypes = IterUtil.mapSnapshot(_args, NodeProperties.NODE_TYPE);
|
|
2585 |
25
| _targs = inferTypeArguments(_tparams, _params, _returned, argTypes, _expected);
|
|
2586 |
25
| return (_targs != null);
|
|
2587 |
| } |
|
2588 |
| |
|
2589 |
2
| @Override public boolean matchesWithBoxing() {
|
|
2590 |
| |
|
2591 |
| |
|
2592 |
2
| return boxArgs() && matches();
|
|
2593 |
| } |
|
2594 |
| |
|
2595 |
2
| @Override public boolean matchesWithVarargs() {
|
|
2596 |
| |
|
2597 |
| |
|
2598 |
2
| if (_paramForVarargs instanceof VarargArrayType) {
|
|
2599 |
0
| ArrayType arrayT = (ArrayType) _paramForVarargs;
|
|
2600 |
0
| Type elementT = arrayT.ofType();
|
|
2601 |
0
| _argForVarargs = boxingConvert(_argForVarargs, elementT);
|
|
2602 |
0
| Iterable<Expression> inferenceArgs = IterUtil.compose(IterUtil.skipLast(_args), _argForVarargs);
|
|
2603 |
0
| Iterable<Type> argTypes = IterUtil.mapSnapshot(inferenceArgs, NodeProperties.NODE_TYPE);
|
|
2604 |
0
| Iterable<Type> paramTypes = IterUtil.compose(IterUtil.skipLast(_params), elementT);
|
|
2605 |
0
| _targs = inferTypeArguments(_tparams, paramTypes, _returned, argTypes, _expected);
|
|
2606 |
0
| if (_targs != null) {
|
|
2607 |
0
| Expression newArg = makeArray((ArrayType) substitute(arrayT, _tparams, _targs),
|
|
2608 |
| IterUtil.make(_argForVarargs)); |
|
2609 |
0
| _args = IterUtil.compose(IterUtil.skipLast(_args), newArg);
|
|
2610 |
0
| return true;
|
|
2611 |
| } |
|
2612 |
| } |
|
2613 |
2
| return false;
|
|
2614 |
| } |
|
2615 |
| } |
|
2616 |
| |
|
2617 |
| |
|
2618 |
| private class EmptyVarargMatcher extends SimpleMatcher { |
|
2619 |
| |
|
2620 |
| |
|
2621 |
| private Type _varargParam; |
|
2622 |
| |
|
2623 |
| |
|
2624 |
216
| public EmptyVarargMatcher(Iterable<? extends Type> params, Iterable<? extends Expression> args,
|
|
2625 |
| Iterable<? extends VariableType> tparams, Iterable<? extends Type> targs) { |
|
2626 |
216
| super(params, args, tparams, targs);
|
|
2627 |
216
| _varargParam = IterUtil.last(_params);
|
|
2628 |
216
| _params = IterUtil.skipLast(_params);
|
|
2629 |
| } |
|
2630 |
| |
|
2631 |
216
| @Override public boolean matches() { return false; }
|
|
2632 |
8
| @Override public boolean matchesWithBoxing() { return false; }
|
|
2633 |
| |
|
2634 |
8
| @Override public boolean matchesWithVarargs() {
|
|
2635 |
8
| if (_varargParam instanceof VarargArrayType) {
|
|
2636 |
8
| boxArgs();
|
|
2637 |
8
| if (super.matches()) {
|
|
2638 |
8
| _params = IterUtil.compose(_params, _varargParam);
|
|
2639 |
8
| ArrayType arrayT = (ArrayType) substitute(_varargParam, _tparams, _targs);
|
|
2640 |
8
| _args = IterUtil.compose(_args, makeArray(arrayT, EMPTY_EXPRESSION_ITERABLE));
|
|
2641 |
8
| return true;
|
|
2642 |
| } |
|
2643 |
| } |
|
2644 |
0
| return false;
|
|
2645 |
| } |
|
2646 |
| |
|
2647 |
| } |
|
2648 |
| |
|
2649 |
| |
|
2650 |
| private class EmptyVarargInferenceMatcher extends InferenceMatcher { |
|
2651 |
| |
|
2652 |
| |
|
2653 |
| private Type _varargParam; |
|
2654 |
| |
|
2655 |
| |
|
2656 |
0
| public EmptyVarargInferenceMatcher(Iterable<? extends Type> params, Iterable<? extends Expression> args,
|
|
2657 |
| Iterable<? extends VariableType> tparams, |
|
2658 |
| Type returned, Option<Type> expected) { |
|
2659 |
0
| super(params, args, tparams, returned, expected);
|
|
2660 |
0
| _varargParam = IterUtil.last(_params);
|
|
2661 |
0
| _params = IterUtil.skipLast(_params);
|
|
2662 |
| } |
|
2663 |
| |
|
2664 |
0
| @Override public boolean matches() { return false; }
|
|
2665 |
0
| @Override public boolean matchesWithBoxing() { return false; }
|
|
2666 |
| |
|
2667 |
0
| @Override public boolean matchesWithVarargs() {
|
|
2668 |
0
| if (_varargParam instanceof VarargArrayType) {
|
|
2669 |
0
| boxArgs();
|
|
2670 |
0
| if (super.matches()) {
|
|
2671 |
0
| _params = IterUtil.compose(_params, _varargParam);
|
|
2672 |
0
| ArrayType arrayT = (ArrayType) substitute(_varargParam, _tparams, _targs);
|
|
2673 |
0
| _args = IterUtil.compose(_args, makeArray(arrayT, EMPTY_EXPRESSION_ITERABLE));
|
|
2674 |
0
| return true;
|
|
2675 |
| } |
|
2676 |
| } |
|
2677 |
0
| return false;
|
|
2678 |
| } |
|
2679 |
| |
|
2680 |
| } |
|
2681 |
| |
|
2682 |
| |
|
2683 |
| private class MultiVarargMatcher extends SimpleMatcher { |
|
2684 |
| |
|
2685 |
| private Type _varargParam; |
|
2686 |
| private Iterable<Expression> _varargArgs; |
|
2687 |
| |
|
2688 |
| |
|
2689 |
12
| public MultiVarargMatcher(Iterable<? extends Type> params, Iterable<? extends Expression> args,
|
|
2690 |
| Iterable<? extends VariableType> tparams, Iterable<? extends Type> targs) { |
|
2691 |
12
| super(params, args, tparams, targs);
|
|
2692 |
12
| _varargParam = IterUtil.last(_params);
|
|
2693 |
12
| _params = IterUtil.skipLast(_params);
|
|
2694 |
12
| Pair<? extends Iterable<Expression>, ? extends Iterable<Expression>> splitArgs =
|
|
2695 |
| IterUtil.split(_args, IterUtil.sizeOf(_params)); |
|
2696 |
12
| _args = splitArgs.first();
|
|
2697 |
12
| _varargArgs = splitArgs.second();
|
|
2698 |
| } |
|
2699 |
| |
|
2700 |
12
| @Override public boolean matches() { return false; }
|
|
2701 |
12
| @Override public boolean matchesWithBoxing() { return false; }
|
|
2702 |
| |
|
2703 |
12
| @Override public boolean matchesWithVarargs() {
|
|
2704 |
12
| if (_varargParam instanceof VarargArrayType) {
|
|
2705 |
8
| boxArgs();
|
|
2706 |
8
| if (super.matches()) {
|
|
2707 |
8
| ArrayType arrayT = (ArrayType) substitute(_varargParam, _tparams, _targs);
|
|
2708 |
8
| Type elementT = arrayT.ofType();
|
|
2709 |
8
| Iterable<Expression> boxedVarargArgs = EMPTY_EXPRESSION_ITERABLE;
|
|
2710 |
8
| for (Expression arg : _varargArgs) {
|
|
2711 |
20
| Expression boxed = boxingConvert(arg, elementT);
|
|
2712 |
| |
|
2713 |
0
| if (!isSubtype(NodeProperties.getType(boxed), elementT)) { return false; }
|
|
2714 |
20
| boxedVarargArgs = IterUtil.compose(boxedVarargArgs, boxed);
|
|
2715 |
| } |
|
2716 |
8
| _params = IterUtil.compose(_params, _varargParam);
|
|
2717 |
8
| _args = IterUtil.compose(_args, makeArray(arrayT, boxedVarargArgs));
|
|
2718 |
8
| return true;
|
|
2719 |
| } |
|
2720 |
| } |
|
2721 |
4
| return false;
|
|
2722 |
| } |
|
2723 |
| |
|
2724 |
| } |
|
2725 |
| |
|
2726 |
| |
|
2727 |
| private class MultiVarargInferenceMatcher extends InferenceMatcher { |
|
2728 |
| |
|
2729 |
| private Type _varargParam; |
|
2730 |
| private Iterable<Expression> _varargArgs; |
|
2731 |
| |
|
2732 |
| |
|
2733 |
0
| public MultiVarargInferenceMatcher(Iterable<? extends Type> params, Iterable<? extends Expression> args,
|
|
2734 |
| Iterable<? extends VariableType> tparams, |
|
2735 |
| Type returned, Option<Type> expected) { |
|
2736 |
0
| super(params, args, tparams, returned, expected);
|
|
2737 |
0
| _varargParam = IterUtil.last(_params);
|
|
2738 |
0
| _params = IterUtil.skipLast(_params);
|
|
2739 |
0
| Pair<? extends Iterable<Expression>, ? extends Iterable<Expression>> splitArgs =
|
|
2740 |
| IterUtil.split(_args, IterUtil.sizeOf(_params)); |
|
2741 |
0
| _args = splitArgs.first();
|
|
2742 |
0
| _varargArgs = splitArgs.second();
|
|
2743 |
| } |
|
2744 |
| |
|
2745 |
0
| @Override public boolean matches() { return false; }
|
|
2746 |
0
| @Override public boolean matchesWithBoxing() { return false; }
|
|
2747 |
| |
|
2748 |
0
| @Override public boolean matchesWithVarargs() {
|
|
2749 |
0
| if (_varargParam instanceof VarargArrayType) {
|
|
2750 |
0
| boxArgs();
|
|
2751 |
0
| ArrayType arrayT = (ArrayType) _varargParam;
|
|
2752 |
0
| final Type elementT = arrayT.ofType();
|
|
2753 |
0
| Lambda<Expression, Expression> makeBoxed = new Lambda<Expression, Expression>() {
|
|
2754 |
0
| public Expression value(Expression e) { return boxingConvert(e, elementT); }
|
|
2755 |
| }; |
|
2756 |
0
| Iterable<Expression> boxedVarargArgs = IterUtil.map(_varargArgs, makeBoxed);
|
|
2757 |
0
| Iterable<Expression> inferenceArgs = IterUtil.compose(_args, boxedVarargArgs);
|
|
2758 |
0
| Iterable<Type> argTypes = IterUtil.mapSnapshot(inferenceArgs, NodeProperties.NODE_TYPE);
|
|
2759 |
0
| Iterable<Type> varargParams = IterUtil.copy(elementT, IterUtil.sizeOf(_varargArgs));
|
|
2760 |
0
| Iterable<Type> paramTypes = IterUtil.compose(_params, varargParams);
|
|
2761 |
0
| _targs = inferTypeArguments(_tparams, paramTypes, _returned, argTypes, _expected);
|
|
2762 |
0
| if (_targs != null) {
|
|
2763 |
0
| _params = IterUtil.compose(_params, _varargParam);
|
|
2764 |
0
| Expression newArg = makeArray((ArrayType) substitute(arrayT, _tparams, _targs), boxedVarargArgs);
|
|
2765 |
0
| _args = IterUtil.compose(_args, newArg);
|
|
2766 |
0
| return true;
|
|
2767 |
| } |
|
2768 |
| } |
|
2769 |
0
| return false;
|
|
2770 |
| } |
|
2771 |
| |
|
2772 |
| } |
|
2773 |
| |
|
2774 |
| } |