001    /* This file was generated with JastAdd2 (http://jastadd.org) version R20130213 */
002    package AST;
003    
004    import java.util.HashSet;
005    import java.io.File;
006    import java.util.*;
007    import beaver.*;
008    import java.util.ArrayList;
009    import java.util.zip.*;
010    import java.io.*;
011    import java.io.FileNotFoundException;
012    import java.util.Collection;
013    /**
014     * Type access for a generic class with an empty type parameter list.
015     * @production DiamondAccess : {@link Access} ::= <span class="component">TypeAccess:{@link Access}</span>;
016     * @ast node
017     * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/TypeInference.ast:4
018     */
019    public class DiamondAccess extends Access implements Cloneable {
020      /**
021       * @apilevel low-level
022       */
023      public void flushCache() {
024      }
025      /**
026       * @apilevel internal
027       */
028      public void flushCollectionCache() {
029      }
030      /**
031       * @apilevel internal
032       */
033      @SuppressWarnings({"unchecked", "cast"})
034      public DiamondAccess clone() throws CloneNotSupportedException {
035        DiamondAccess node = (DiamondAccess)super.clone();
036        node.type_computed = false;
037        node.type_value = null;
038        node.typeArguments_MethodDecl_values = null;
039        node.in$Circle(false);
040        node.is$Final(false);
041        return node;
042      }
043    /**
044     * @apilevel internal
045     */
046      @SuppressWarnings({"unchecked", "cast"})
047    public DiamondAccess copy() {
048      
049      try {
050        DiamondAccess node = (DiamondAccess) clone();
051        node.parent = null;
052        if(children != null)
053          node.children = (ASTNode[]) children.clone();
054        
055        return node;
056      } catch (CloneNotSupportedException e) {
057        throw new Error("Error: clone not supported for " + getClass().getName());
058      }
059      
060    }/**
061     * Create a deep copy of the AST subtree at this node.
062     * The copy is dangling, i.e. has no parent.
063     * @return dangling copy of the subtree at this node
064     * @apilevel low-level
065     */
066      @SuppressWarnings({"unchecked", "cast"})
067    public DiamondAccess fullCopy() {
068      
069      DiamondAccess tree = (DiamondAccess) copy();
070      if (children != null) {
071        for (int i = 0; i < children.length; ++i) {
072          
073          ASTNode child = (ASTNode) children[i];
074          if(child != null) {
075            child = child.fullCopy();
076            tree.setChild(child, i);
077          }
078        }
079      }
080      return tree;
081      
082    }  /**
083       * @ast method 
084       * @aspect TypeInference
085       * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/TypeInference.jrag:72
086       */
087      protected static SimpleSet mostSpecific(
088                        SimpleSet maxSpecific, MethodDecl decl) {
089                if (maxSpecific.isEmpty()) {
090                        maxSpecific = maxSpecific.add(decl);
091                } else {
092                        if (decl.moreSpecificThan(
093                                                (MethodDecl)maxSpecific.iterator().next()))
094                                maxSpecific = SimpleSet.emptySet.add(decl);
095                        else if (!((MethodDecl)maxSpecific.iterator().next()).
096                                        moreSpecificThan(decl))
097                                maxSpecific = maxSpecific.add(decl);
098                }
099                return maxSpecific;
100       }
101      /**
102        * Choose a constructor for the diamond operator using placeholder
103        * methods.
104        * @ast method 
105       * @aspect TypeInference
106       * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/TypeInference.jrag:91
107       */
108      protected SimpleSet chooseConstructor() {
109               ClassInstanceExpr instanceExpr = getClassInstanceExpr();
110               TypeDecl type = getTypeAccess().type();
111    
112               assert instanceExpr != null;
113               assert type instanceof ParClassDecl;
114    
115               GenericClassDecl genericType =
116                       (GenericClassDecl) ((ParClassDecl)type).genericDecl();
117    
118               List<PlaceholderMethodDecl> placeholderMethods =
119                       genericType.getPlaceholderMethodList();
120    
121               SimpleSet maxSpecific = SimpleSet.emptySet;
122               Collection<MethodDecl> potentiallyApplicable =
123                       potentiallyApplicable(placeholderMethods);
124               for (MethodDecl candidate : potentiallyApplicable) {
125                       if (applicableBySubtyping(instanceExpr, candidate) ||
126                                       applicableByMethodInvocationConversion(
127                                               instanceExpr, candidate) ||
128                                       applicableByVariableArity(instanceExpr, candidate))
129                               maxSpecific = mostSpecific(maxSpecific, candidate);
130    
131               }
132               return maxSpecific;
133       }
134      /**
135        * Select potentially applicable method declarations
136        * from a set of candidates.
137        * Type inference is applied to the (potentially) applicable candidates.
138        * @ast method 
139       * @aspect TypeInference
140       * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/TypeInference.jrag:224
141       */
142      protected Collection<MethodDecl> potentiallyApplicable(
143                       List<PlaceholderMethodDecl> candidates) {
144               Collection<MethodDecl> potentiallyApplicable =
145                       new LinkedList<MethodDecl>();
146               for (GenericMethodDecl candidate : candidates) {
147                       if (potentiallyApplicable(candidate)) {
148                               MethodDecl decl = candidate.lookupParMethodDecl(
149                                               typeArguments(candidate));
150                               potentiallyApplicable.add(decl);
151                       }
152               }
153               return potentiallyApplicable;
154       }
155      /**
156        * @return false if the candidate method is not applicable.
157        * @ast method 
158       * @aspect TypeInference
159       * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/TypeInference.jrag:241
160       */
161      protected boolean potentiallyApplicable(
162                       GenericMethodDecl candidate) {
163               if (candidate.isVariableArity() &&
164                               !(getClassInstanceExpr().arity() >= candidate.arity()-1))
165                       return false;
166               if (!candidate.isVariableArity() &&
167                               !(getClassInstanceExpr().arity() == candidate.arity()))
168                       return false;
169    
170               java.util.List<TypeDecl> typeArgs = typeArguments(candidate);
171               if (typeArgs.size() != 0) {
172                       if (candidate.getNumTypeParameter() != typeArgs.size())
173                               return false;
174                       for (int i = 0; i < candidate.getNumTypeParameter(); i++)
175                               if (!typeArgs.get(i).subtype(
176                                                       candidate.original().getTypeParameter(i)))
177                                       return false;
178               }
179               return true;
180       }
181      /**
182        * Diamond type inference.
183        * @ast method 
184       * @aspect TypeInference
185       * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/TypeInference.jrag:297
186       */
187      public Collection<TypeDecl> computeConstraints(
188                       GenericMethodDecl decl) {
189               Constraints c = new Constraints();
190               // store type parameters
191               for (int i = 0; i < decl.original().getNumTypeParameter(); i++)
192                       c.addTypeVariable(decl.original().getTypeParameter(i));
193    
194               ClassInstanceExpr instanceExpr = getClassInstanceExpr();
195               for (int i = 0; i < instanceExpr.getNumArg(); i++) {
196                       TypeDecl A = instanceExpr.getArg(i).type();
197                       int index = i >= decl.getNumParameter() ?
198                               decl.getNumParameter() - 1 : i;
199                       TypeDecl F = decl.getParameter(index).type();
200                       if (decl.getParameter(index) instanceof
201                                       VariableArityParameterDeclaration &&
202                                       (instanceExpr.getNumArg() != decl.getNumParameter() ||
203                                       !A.isArrayDecl())) {
204                               F = F.componentType();
205                       }
206                       c.convertibleTo(A, F);
207               }
208               if (c.rawAccess)
209                       return new ArrayList();
210    
211               c.resolveEqualityConstraints();
212               c.resolveSupertypeConstraints();
213    
214               if (c.unresolvedTypeArguments()) {
215                       TypeDecl S = assignConvertedType();
216                       if (S.isUnboxedPrimitive())
217                               S = S.boxed();
218                       TypeDecl R = decl.type();
219                       if (R.isVoid())
220                               R = typeObject();
221    
222                       c.convertibleFrom(S, R);
223                       c.resolveEqualityConstraints();
224                       c.resolveSupertypeConstraints();
225                       c.resolveSubtypeConstraints();
226               }
227    
228               return c.typeArguments();
229       }
230      /**
231        * @return true if the method is applicable by subtyping
232        * @ast method 
233       * @aspect TypeInference
234       * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/TypeInference.jrag:344
235       */
236      protected boolean applicableBySubtyping(
237                       ClassInstanceExpr expr, MethodDecl method) {
238               if (method.getNumParameter() != expr.getNumArg())
239                       return false;
240               for (int i = 0; i < method.getNumParameter(); i++)
241                       if(!expr.getArg(i).type().instanceOf(method.getParameter(i).type()))
242                               return false;
243               return true;
244       }
245      /**
246        * @return true if the method is applicable by method invocation conversion
247        * @ast method 
248       * @aspect TypeInference
249       * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/TypeInference.jrag:357
250       */
251      protected boolean applicableByMethodInvocationConversion(
252                       ClassInstanceExpr expr, MethodDecl method) {
253               if (method.getNumParameter() != expr.getNumArg())
254                       return false;
255               for (int i = 0; i < method.getNumParameter(); i++)
256                       if (!expr.getArg(i).type().methodInvocationConversionTo(
257                                               method.getParameter(i).type()))
258                               return false;
259               return true;
260       }
261      /**
262        * @return true if the method is applicable by variable arity
263        * @ast method 
264       * @aspect TypeInference
265       * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/TypeInference.jrag:371
266       */
267      protected boolean applicableByVariableArity(
268                       ClassInstanceExpr expr, MethodDecl method) {
269               for (int i = 0; i < method.getNumParameter() - 1; i++)
270                       if(!expr.getArg(i).type().methodInvocationConversionTo(
271                                               method.getParameter(i).type()))
272                               return false;
273               for (int i = method.getNumParameter() - 1; i < expr.getNumArg(); i++)
274                       if (!expr.getArg(i).type().methodInvocationConversionTo(
275                                               method.lastParameter().type().componentType()))
276                               return false;
277               return true;
278       }
279      /**
280        * Checks if this diamond access is legal.
281        * The diamond access is not legal if it either is part of an inner class
282        * declaration, if it is used to access a non-generic type, or if it is
283        * part of a call to a generic constructor with explicit type arguments.
284        * @ast method 
285       * @aspect TypeInference
286       * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/TypeInference.jrag:487
287       */
288      public void typeCheck() {
289               if (isAnonymousDecl())
290                       error("the diamond operator can not be used with "+
291                                       "anonymous classes");
292               if (isExplicitGenericConstructorAccess())
293                       error("the diamond operator may not be used with generic "+
294                                       "constructors with explicit type parameters");
295               if (getClassInstanceExpr() == null)
296                       error("the diamond operator can only be used in "+
297                                       "class instance expressions");
298               if (!(getTypeAccess().type() instanceof ParClassDecl))
299                       error("the diamond operator can only be used to "+
300                                       "instantiate generic classes");
301       }
302      /**
303        * Pretty printing of diamond access.
304        * @ast method 
305       * @aspect TypeInference
306       * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/TypeInference.jrag:505
307       */
308      public void toString(StringBuffer sb) {
309               getTypeAccess().toString(sb);
310               sb.append("<>");
311       }
312      /**
313       * @ast method 
314       * 
315       */
316      public DiamondAccess() {
317        super();
318    
319    
320      }
321      /**
322       * Initializes the child array to the correct size.
323       * Initializes List and Opt nta children.
324       * @apilevel internal
325       * @ast method
326       * @ast method 
327       * 
328       */
329      public void init$Children() {
330        children = new ASTNode[1];
331      }
332      /**
333       * @ast method 
334       * 
335       */
336      public DiamondAccess(Access p0) {
337        setChild(p0, 0);
338      }
339      /**
340       * @apilevel low-level
341       * @ast method 
342       * 
343       */
344      protected int numChildren() {
345        return 1;
346      }
347      /**
348       * @apilevel internal
349       * @ast method 
350       * 
351       */
352      public boolean mayHaveRewrite() {
353        return false;
354      }
355      /**
356       * Replaces the TypeAccess child.
357       * @param node The new node to replace the TypeAccess child.
358       * @apilevel high-level
359       * @ast method 
360       * 
361       */
362      public void setTypeAccess(Access node) {
363        setChild(node, 0);
364      }
365      /**
366       * Retrieves the TypeAccess child.
367       * @return The current node used as the TypeAccess child.
368       * @apilevel high-level
369       * @ast method 
370       * 
371       */
372      public Access getTypeAccess() {
373        return (Access)getChild(0);
374      }
375      /**
376       * Retrieves the TypeAccess child.
377       * <p><em>This method does not invoke AST transformations.</em></p>
378       * @return The current node used as the TypeAccess child.
379       * @apilevel low-level
380       * @ast method 
381       * 
382       */
383      public Access getTypeAccessNoTransform() {
384        return (Access)getChildNoTransform(0);
385      }
386      /**
387       * @apilevel internal
388       */
389      protected boolean type_computed = false;
390      /**
391       * @apilevel internal
392       */
393      protected TypeDecl type_value;
394      /**
395        * If this DiamondAccess node constitutes a legal use of
396        * the diamond operator, the inferred generic type for the
397        * enclosing class instance expression is returned.
398        * @attribute syn
399       * @aspect TypeInference
400       * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/TypeInference.jrag:39
401       */
402      @SuppressWarnings({"unchecked", "cast"})
403      public TypeDecl type() {
404        if(type_computed) {
405          return type_value;
406        }
407          ASTNode$State state = state();
408      int num = state.boundariesCrossed;
409      boolean isFinal = this.is$Final();
410        type_value = type_compute();
411      if(isFinal && num == state().boundariesCrossed){ type_computed = true; }
412            return type_value;
413      }
414      /**
415       * @apilevel internal
416       */
417      private TypeDecl type_compute() {
418               TypeDecl accessType = getTypeAccess().type();
419    
420               if (isAnonymousDecl())
421                       return accessType;
422    
423               if (getClassInstanceExpr() == null)
424                       // it is an error if the DiamondAccess does not occurr
425                       // within a class instance creation expression, but this
426                       // error is handled in typeCheck
427                       return accessType;
428    
429               if (!(accessType instanceof ParClassDecl))
430                       // it is an error if the TypeDecl of a DiamondAccess is not
431                       // a generic type, but this error is handled in typeCheck
432                       return accessType;
433    
434               SimpleSet maxSpecific = chooseConstructor();
435    
436               if (maxSpecific.isEmpty())
437                       return getTypeAccess().type();
438    
439               MethodDecl constructor = (MethodDecl) maxSpecific.iterator().next();
440               return constructor.type();
441       }
442      /**
443       * @attribute syn
444       * @aspect TypeInference
445       * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/TypeInference.jrag:65
446       */
447      public boolean isDiamond() {
448        ASTNode$State state = state();
449        try {  return true;  }
450        finally {
451        }
452      }
453      protected java.util.Map typeArguments_MethodDecl_values;
454      /**
455        * Type inference for placeholder methods.
456        * @attribute syn
457       * @aspect TypeInference
458       * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/TypeInference.jrag:267
459       */
460      @SuppressWarnings({"unchecked", "cast"})
461      public java.util.List<TypeDecl> typeArguments(MethodDecl decl) {
462        Object _parameters = decl;
463        if(typeArguments_MethodDecl_values == null) typeArguments_MethodDecl_values = new java.util.HashMap(4);
464        if(typeArguments_MethodDecl_values.containsKey(_parameters)) {
465          return (java.util.List<TypeDecl>)typeArguments_MethodDecl_values.get(_parameters);
466        }
467          ASTNode$State state = state();
468      int num = state.boundariesCrossed;
469      boolean isFinal = this.is$Final();
470        java.util.List<TypeDecl> typeArguments_MethodDecl_value = typeArguments_compute(decl);
471      if(isFinal && num == state().boundariesCrossed){ typeArguments_MethodDecl_values.put(_parameters, typeArguments_MethodDecl_value); }
472            return typeArguments_MethodDecl_value;
473      }
474      /**
475       * @apilevel internal
476       */
477      private java.util.List<TypeDecl> typeArguments_compute(MethodDecl decl) {
478               java.util.List<TypeDecl> typeArguments = new LinkedList<TypeDecl>();
479               if (decl instanceof GenericMethodDecl) {
480                       GenericMethodDecl method = (GenericMethodDecl) decl;
481                       Collection<TypeDecl> arguments = computeConstraints(method);
482                       if (arguments.isEmpty())
483                               return typeArguments;
484                       int i = 0;
485                       for (TypeDecl argument : arguments) {
486                               if (argument == null) {
487                                       TypeVariable v = method.original().getTypeParameter(i);
488                                       if (v.getNumTypeBound() == 0)
489                                               argument = typeObject();
490                                       else if (v.getNumTypeBound() == 1)
491                                               argument = v.getTypeBound(0).type();
492                                       else
493                                               argument = v.lubType();
494                               }
495                               typeArguments.add(argument);
496    
497                               i += 1;
498                       }
499               }
500               return typeArguments;
501       }
502      /**
503       * @attribute inh
504       * @aspect TypeInference
505       * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/TypeInference.jrag:68
506       */
507      @SuppressWarnings({"unchecked", "cast"})
508      public ClassInstanceExpr getClassInstanceExpr() {
509          ASTNode$State state = state();
510        ClassInstanceExpr getClassInstanceExpr_value = getParent().Define_ClassInstanceExpr_getClassInstanceExpr(this, null);
511            return getClassInstanceExpr_value;
512      }
513      /**
514       * @attribute inh
515       * @aspect TypeInference
516       * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/TypeInference.jrag:262
517       */
518      @SuppressWarnings({"unchecked", "cast"})
519      public TypeDecl typeObject() {
520          ASTNode$State state = state();
521        TypeDecl typeObject_value = getParent().Define_TypeDecl_typeObject(this, null);
522            return typeObject_value;
523      }
524      /**
525        * @return true if this access is part of an anonymous class declaration
526        * @attribute inh
527       * @aspect TypeInference
528       * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/TypeInference.jrag:452
529       */
530      @SuppressWarnings({"unchecked", "cast"})
531      public boolean isAnonymousDecl() {
532          ASTNode$State state = state();
533        boolean isAnonymousDecl_value = getParent().Define_boolean_isAnonymousDecl(this, null);
534            return isAnonymousDecl_value;
535      }
536      /**
537        * @return true if the Access is part of a generic constructor invocation
538        * with explicit type arguments
539        * @attribute inh
540       * @aspect TypeInference
541       * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/TypeInference.jrag:468
542       */
543      @SuppressWarnings({"unchecked", "cast"})
544      public boolean isExplicitGenericConstructorAccess() {
545          ASTNode$State state = state();
546        boolean isExplicitGenericConstructorAccess_value = getParent().Define_boolean_isExplicitGenericConstructorAccess(this, null);
547            return isExplicitGenericConstructorAccess_value;
548      }
549      /**
550       * @apilevel internal
551       */
552      public ASTNode rewriteTo() {
553        return super.rewriteTo();
554      }
555    }