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 BoundNames { 011 public Access FieldDeclaration.createQualifiedBoundAccess() { 012 if(isStatic()) 013 return hostType().createQualifiedAccess().qualifiesAccess(new BoundFieldAccess(this)); 014 else 015 return new ThisAccess("this").qualifiesAccess( 016 new BoundFieldAccess(this)); 017 } 018 019 // The memberMethods(String name) attribute is used to lookup member methods. 020 // It uses the methodsNameMap() map where a name is mapped to a list of member 021 // methods. We extend the map with the declaration m by either appending 022 // it to an existing list of declarations or adding a new list. That list 023 // will be used to name bind a new qualified name access. 024 public MethodDecl TypeDecl.addMemberMethod(MethodDecl m) { 025 addBodyDecl(m); 026 return (MethodDecl)getBodyDecl(getNumBodyDecl()-1); 027 /* 028 HashMap map = methodsNameMap(); 029 ArrayList list = (ArrayList)map.get(m.name()); 030 if(list == null) { 031 list = new ArrayList(4); 032 map.put(m.name(), list); 033 } 034 list.add(m); 035 if(!memberMethods(m.name()).contains(m)) 036 throw new Error("The method " + m.signature() + " added to " + typeName() + " can not be found using lookupMemberMethod"); 037 */ 038 } 039 040 public ConstructorDecl TypeDecl.addConstructor(ConstructorDecl c) { 041 addBodyDecl(c); 042 return (ConstructorDecl)getBodyDecl(getNumBodyDecl()-1); 043 } 044 045 public ClassDecl TypeDecl.addMemberClass(ClassDecl c) { 046 addBodyDecl(new MemberClassDecl(c)); 047 return ((MemberClassDecl)getBodyDecl(getNumBodyDecl()-1)).getClassDecl(); 048 } 049 050 051 // the new field must be unique otherwise an error occurs 052 public FieldDeclaration TypeDecl.addMemberField(FieldDeclaration f) { 053 addBodyDecl(f); 054 return (FieldDeclaration)getBodyDecl(getNumBodyDecl()-1); 055 //if(!memberFields(f.name()).contains(f)) 056 // throw new Error("The field " + f.name() + " added to " + typeName() + " can not be found using lookupMemberField"); 057 } 058 059 // A BoundMethodAccess is a MethodAccess where the name analysis is bypassed by explicitly setting the desired binding 060 // this is useful when name binding is cached and recomputation is undesired 061 public BoundMethodAccess.BoundMethodAccess(String name, List args, MethodDecl methodDecl) { 062 this(name, args); 063 this.methodDecl = methodDecl; 064 } 065 private MethodDecl BoundMethodAccess.methodDecl; 066 eq BoundMethodAccess.decl() = methodDecl; 067 068 public BoundFieldAccess.BoundFieldAccess(FieldDeclaration f) { 069 this(f.name(), f); 070 } 071 072 eq BoundFieldAccess.decl() = getFieldDeclaration(); 073 public boolean BoundFieldAccess.isExactVarAccess() { 074 return false; 075 } 076 077 public Access MethodDecl.createBoundAccess(List args) { 078 if(isStatic()) { 079 return hostType().createQualifiedAccess().qualifiesAccess( 080 new BoundMethodAccess(name(), args, this) 081 ); 082 } 083 return new BoundMethodAccess(name(), args, this); 084 } 085 086 public Access FieldDeclaration.createBoundFieldAccess() { 087 return createQualifiedBoundAccess(); 088 } 089 090 public TypeAccess TypeDecl.createBoundAccess() { 091 return new BoundTypeAccess("", name(), this); 092 } 093 eq BoundTypeAccess.decls() = SimpleSet.emptySet.add(getTypeDecl()); 094 095 rewrite BytecodeTypeAccess { 096 to Access { 097 if(name().indexOf("$") == -1) 098 return new TypeAccess(packageName(), name()); 099 else { 100 String[] names = name().split("\\$"); 101 Access a = null; // the resulting access 102 String newName = null; // the subname to try 103 TypeDecl type = null; // qualifying type if one 104 for(int i = 0; i < names.length; i++) { 105 newName = newName == null ? names[i] : (newName + "$" + names[i]); 106 SimpleSet set; 107 if(type != null) 108 set = type.memberTypes(newName); 109 else if(packageName().equals("")) 110 set = lookupType(newName); 111 else { 112 TypeDecl typeDecl = lookupType(packageName(), newName); 113 set = SimpleSet.emptySet; 114 if(typeDecl != null) 115 set = set.add(typeDecl); 116 } 117 if(!set.isEmpty()) { 118 a = a == null ? (Access)new TypeAccess(packageName(), newName) : (Access)a.qualifiesAccess(new TypeAccess(newName)); 119 type = (TypeDecl)set.iterator().next(); 120 newName = null; // reset subname 121 } 122 } 123 if(a == null) { 124 a = new TypeAccess(packageName(), name()); 125 } 126 return a; 127 } 128 } 129 } 130 }