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 }