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 Java2Rewrites { 011 int TypeDecl.uniqueIndexCounter = 1; 012 syn lazy int TypeDecl.uniqueIndex() = topLevelType().uniqueIndexCounter++; 013 014 015 syn lazy String TypeDecl.jvmName() { 016 throw new Error("Jvm name only supported for reference types and not " + getClass().getName()); 017 } 018 eq ReferenceType.jvmName() { 019 if(!isNestedType()) 020 return fullName(); 021 else if(isAnonymous() || isLocalClass()) 022 return enclosingType().jvmName() + "$" + uniqueIndex() + name(); 023 else 024 return enclosingType().jvmName() + "$" + name(); 025 } 026 eq ArrayDecl.jvmName() { 027 StringBuffer dim = new StringBuffer(); 028 for(int i = 0; i < dimension(); i++) 029 dim.append("["); 030 if(elementType().isReferenceType()) 031 return dim.toString() + "L" + elementType().jvmName() + ";"; 032 else 033 return dim.toString() + elementType().jvmName(); 034 } 035 eq ByteType.jvmName() = "B"; 036 eq CharType.jvmName() = "C"; 037 eq ShortType.jvmName() = "S"; 038 eq IntType.jvmName() = "I"; 039 eq LongType.jvmName() = "J"; 040 eq FloatType.jvmName() = "F"; 041 eq DoubleType.jvmName() = "D"; 042 eq BooleanType.jvmName() = "Z"; 043 044 syn String TypeDecl.primitiveClassName() { 045 throw new Error("primitiveClassName not supported for " + name() + " of type " + getClass().getName()); 046 } 047 eq ByteType.primitiveClassName() = "Byte"; 048 eq CharType.primitiveClassName() = "Character"; 049 eq ShortType.primitiveClassName() = "Short"; 050 eq IntType.primitiveClassName() = "Integer"; 051 eq LongType.primitiveClassName() = "Long"; 052 eq FloatType.primitiveClassName() = "Float"; 053 eq DoubleType.primitiveClassName() = "Double"; 054 eq BooleanType.primitiveClassName() = "Boolean"; 055 eq VoidType.primitiveClassName() = "Void"; 056 057 syn String TypeDecl.referenceClassFieldName() { 058 throw new Error("referenceClassFieldName not supported for " + name() + " of type " + getClass().getName()); 059 } 060 eq ReferenceType.referenceClassFieldName() = "class$" + jvmName().replace('[', '$').replace('.', '$').replace(';', ' ').trim(); 061 eq ArrayDecl.referenceClassFieldName() = "array" + jvmName().replace('[', '$').replace('.', '$').replace(';', ' ').trim(); 062 063 064 // lazily build a static field for assertionsDisabled 065 private FieldDeclaration TypeDecl.createAssertionsDisabled = null; 066 public FieldDeclaration TypeDecl.createAssertionsDisabled() { 067 if(createAssertionsDisabled != null) 068 return createAssertionsDisabled; 069 // static final boolean $assertionsDisabled = !TypeName.class.desiredAssertionStatus(); 070 createAssertionsDisabled = new FieldDeclaration( 071 new Modifiers(new List().add(new Modifier("public")).add(new Modifier("static")).add(new Modifier("final"))), 072 new PrimitiveTypeAccess("boolean"), 073 "$assertionsDisabled", 074 new Opt( 075 new LogNotExpr( 076 topLevelType().createQualifiedAccess().qualifiesAccess( 077 new ClassAccess().qualifiesAccess( 078 new MethodAccess( 079 "desiredAssertionStatus", 080 new List() 081 ) 082 ) 083 ) 084 ) 085 ) 086 ); 087 getBodyDeclList().insertChild(createAssertionsDisabled, 0); 088 // explicit read to trigger possible rewrites 089 createAssertionsDisabled = (FieldDeclaration)getBodyDeclList().getChild(0); 090 // transform the generated initalization, e.g., the ClassAccess construct 091 createAssertionsDisabled.transformation(); 092 return createAssertionsDisabled; 093 } 094 095 public FieldDeclaration InterfaceDecl.createStaticClassField(String name) { 096 return methodHolder().createStaticClassField(name); 097 } 098 public MethodDecl InterfaceDecl.createStaticClassMethod() { 099 return methodHolder().createStaticClassMethod(); 100 } 101 // create anonymous class to delegate to 102 private TypeDecl InterfaceDecl.methodHolder = null; 103 public TypeDecl InterfaceDecl.methodHolder() { 104 if(methodHolder != null) 105 return methodHolder; 106 String name = "$" + nextAnonymousIndex(); 107 ClassDecl c = addMemberClass(new ClassDecl( 108 new Modifiers(new List()), 109 name, 110 new Opt(), 111 new List(), 112 new List() 113 )); 114 methodHolder = c; 115 return c; 116 } 117 118 // lazily build a static field for each typename used in a .class expression 119 private HashMap TypeDecl.createStaticClassField = null; 120 public FieldDeclaration TypeDecl.createStaticClassField(String name) { 121 if(createStaticClassField == null) 122 createStaticClassField = new HashMap(); 123 if(createStaticClassField.containsKey(name)) 124 return (FieldDeclaration)createStaticClassField.get(name); 125 // static synthetic Class class$java$lang$String; 126 FieldDeclaration f = new FieldDeclaration( 127 new Modifiers(new List().add(new Modifier("public")).add(new Modifier("static"))), 128 lookupType("java.lang", "Class").createQualifiedAccess(), 129 name, 130 new Opt() 131 ) { 132 public boolean isConstant() { 133 return true; 134 } 135 }; 136 createStaticClassField.put(name, f); 137 return addMemberField(f); 138 } 139 140 // lazily build a static class$ method in this type declaration 141 private MethodDecl TypeDecl.createStaticClassMethod = null; 142 public MethodDecl TypeDecl.createStaticClassMethod() { 143 if(createStaticClassMethod != null) 144 return createStaticClassMethod; 145 // static synthetic Class class$(String name) { 146 // try { 147 // return java.lang.Class.forName(name); 148 // } catch(java.lang.ClassNotFoundException e) { 149 // throw new java.lang.NoClassDefFoundError(e.getMessage()); 150 // } 151 // } 152 createStaticClassMethod = new MethodDecl( 153 new Modifiers(new List().add(new Modifier("public")).add(new Modifier("static"))), 154 lookupType("java.lang", "Class").createQualifiedAccess(), 155 "class$", 156 new List().add( 157 new ParameterDeclaration( 158 new Modifiers(new List()), 159 lookupType("java.lang", "String").createQualifiedAccess(), 160 "name" 161 ) 162 ), 163 new List(), 164 new Opt( 165 new Block( 166 new List().add( 167 new TryStmt( 168 new Block( 169 new List().add( 170 new ReturnStmt( 171 new Opt( 172 lookupType("java.lang", "Class").createQualifiedAccess().qualifiesAccess( 173 new MethodAccess( 174 "forName", 175 new List().add( 176 new VarAccess("name") 177 ) 178 ) 179 ) 180 ) 181 ) 182 ) 183 ), 184 new List().add( 185 new BasicCatch( 186 new ParameterDeclaration( 187 new Modifiers(new List()), 188 lookupType("java.lang", "ClassNotFoundException").createQualifiedAccess(), 189 "e" 190 ), 191 new Block( 192 new List().add( 193 new ThrowStmt( 194 new ClassInstanceExpr( 195 lookupType("java.lang", "NoClassDefFoundError").createQualifiedAccess(), 196 new List().add( 197 new VarAccess("e").qualifiesAccess( 198 new MethodAccess( 199 "getMessage", 200 new List() 201 ) 202 ) 203 ), 204 new Opt() 205 ) 206 ) 207 ) 208 ) 209 ) 210 ), 211 new Opt() 212 ) 213 ) 214 ) 215 ) 216 ) { 217 public boolean isConstant() { 218 return true; 219 } 220 }; 221 return addMemberMethod(createStaticClassMethod); 222 } 223 224 }