001    /*
002     * The JastAdd Extensible Java Compiler (http://jastadd.org) is covered
003     * by the modified BSD License. You should have received a copy of the
004     * modified BSD license with this compiler.
005     * 
006     * Copyright (c) 2005-2008, Torbjorn Ekman
007     * All rights reserved.
008     */
009    
010    aspect GenericTypeVariables {
011      
012      // The bounds of a type variable should be resolved to type names
013      eq TypeVariable.getTypeBound().nameType() = NameType.TYPE_NAME;
014    
015      rewrite TypeVariable {
016        when (getNumTypeBound() == 0)
017        to TypeVariable {
018          addTypeBound(
019            new TypeAccess(
020              "java.lang",
021              "Object"
022            )
023          );
024          return this;
025        }
026      }
027    
028      public void TypeVariable.nameCheck() {
029        if(extractSingleType(lookupType(name())) != this)
030          error("*** Semantic Error: type variable " + name() + " is multiply declared");
031      }
032    
033      syn TypeDecl TypeVariable.lowerBound() = getTypeBound(0).type();
034      
035    }
036    
037    aspect GenericTypeVariablesMembers {
038      eq TypeVariable.memberMethods(String name) {
039        Collection list = new HashSet();
040        for(int i = 0; i < getNumTypeBound(); i++) {
041          for(Iterator iter = getTypeBound(i).type().memberMethods(name).iterator(); iter.hasNext(); ) {
042            MethodDecl decl = (MethodDecl)iter.next();
043            //if(decl.accessibleFrom(hostType()))
044              list.add(decl);
045          }
046        }
047        return list;
048      }
049      
050      eq TypeVariable.memberFields(String name) {
051        SimpleSet set = SimpleSet.emptySet;
052        for(int i = 0; i < getNumTypeBound(); i++) {
053          for(Iterator iter = getTypeBound(i).type().memberFields(name).iterator(); iter.hasNext(); ) {
054            FieldDeclaration decl = (FieldDeclaration)iter.next();
055            //if(decl.accessibleFrom(hostType()))
056              set = set.add(decl);
057          }
058        }
059        return set;
060      }
061    
062    }
063    
064    aspect GenricTypeVariablesTypeAnalysis {
065    
066      public void TypeVariable.typeCheck() {
067        if(!getTypeBound(0).type().isTypeVariable() && !getTypeBound(0).type().isClassDecl() && !getTypeBound(0).type().isInterfaceDecl()) {
068          error("the first type bound must be either a type variable, or a class or interface type which " + 
069            getTypeBound(0).type().fullName() + " is not");
070        }
071        for(int i = 1; i < getNumTypeBound(); i++) {
072          if(!getTypeBound(i).type().isInterfaceDecl()) {
073            error("type bound " + i + " must be an interface type which " + 
074              getTypeBound(i).type().fullName() + " is not");
075          }
076        }
077        HashSet typeSet = new HashSet();
078        for(int i = 0; i < getNumTypeBound(); i++) {
079          TypeDecl type = getTypeBound(i).type();
080          TypeDecl erasure = type.erasure();
081          if(typeSet.contains(erasure)) {
082            if(type != erasure) {
083              error("the erasure " + erasure.fullName() + " of typebound " + getTypeBound(i) + " is multiply declared in " + this);
084            }
085            else {
086              error(type.fullName() + " is multiply declared");
087            }
088          }
089          typeSet.add(erasure);
090        }
091    
092        for(int i = 0; i < getNumTypeBound(); i++) {
093          TypeDecl type = getTypeBound(i).type();
094          for(Iterator iter = type.methodsIterator(); iter.hasNext(); ) {
095            MethodDecl m = (MethodDecl)iter.next();
096            for(int j = i+1; j < getNumTypeBound(); j++) {
097              TypeDecl destType = getTypeBound(j).type();
098              for(Iterator destIter = destType.memberMethods(m.name()).iterator(); destIter.hasNext(); ) {
099                MethodDecl n = (MethodDecl)destIter.next();
100                if(m.sameSignature(n) && m.type() != n.type()) {
101                  error("the two bounds, " + type.name() + " and " + destType.name() + ", in type variable " + name() + 
102                    " have a method " + m.signature() + " with conflicting return types " + m.type().name() + " and " + n.type().name());
103                }
104              }
105            }
106          }
107        }
108    
109        
110      }
111      
112      
113    }