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 GenericsCodegen { 011 refine InnerClasses eq ClassDecl.superEnclosing() { 012 return superclass().erasure().enclosing(); 013 } 014 015 eq TypeVariable.typeDescriptor() = erasure().typeDescriptor(); 016 eq ParClassDecl.typeDescriptor() = erasure().typeDescriptor(); 017 eq ParInterfaceDecl.typeDescriptor() = erasure().typeDescriptor(); 018 019 eq GenericClassDeclSubstituted.typeDescriptor() = original().typeDescriptor(); 020 eq GenericInterfaceDeclSubstituted.typeDescriptor() = original().typeDescriptor(); 021 eq ClassDeclSubstituted.typeDescriptor() = original().typeDescriptor(); 022 eq InterfaceDeclSubstituted.typeDescriptor() = original().typeDescriptor(); 023 024 eq GenericClassDeclSubstituted.constantPoolName() = original().constantPoolName(); 025 eq GenericInterfaceDeclSubstituted.constantPoolName() = original().constantPoolName(); 026 eq ClassDeclSubstituted.constantPoolName() = original().constantPoolName(); 027 eq InterfaceDeclSubstituted.constantPoolName() = original().constantPoolName(); 028 029 eq ClassDeclSubstituted.uniqueIndex() = original().uniqueIndex(); 030 eq GenericClassDeclSubstituted.uniqueIndex() = original().uniqueIndex(); 031 eq InterfaceDeclSubstituted.uniqueIndex() = original().uniqueIndex(); 032 eq GenericInterfaceDeclSubstituted.uniqueIndex() = original().uniqueIndex(); 033 eq ParTypeDecl.uniqueIndex() = genericDecl().uniqueIndex(); 034 035 eq TypeVariable.arrayTypeDescriptor() = erasure().arrayTypeDescriptor(); 036 eq ParClassDecl.arrayTypeDescriptor() = erasure().arrayTypeDescriptor(); 037 eq ParInterfaceDecl.arrayTypeDescriptor() = erasure().arrayTypeDescriptor(); 038 //eq WildcardType.typeDescriptor() = erasure().typeDescriptor(); 039 040 eq GenericClassDeclSubstituted.arrayTypeDescriptor() = original().arrayTypeDescriptor(); 041 eq GenericInterfaceDeclSubstituted.arrayTypeDescriptor() = original().arrayTypeDescriptor(); 042 eq ClassDeclSubstituted.arrayTypeDescriptor() = original().arrayTypeDescriptor(); 043 eq InterfaceDeclSubstituted.arrayTypeDescriptor() = original().arrayTypeDescriptor(); 044 045 public ConstructorDecl ConstructorDeclSubstituted.createAccessor() { 046 return sourceConstructorDecl().createAccessor(); 047 } 048 049 protected TypeDecl ConstructorDeclSubstituted.createAnonymousJavaTypeDecl() { 050 return sourceConstructorDecl().createAnonymousJavaTypeDecl(); 051 } 052 053 syn FieldDeclaration FieldDeclaration.erasedField() = this; 054 eq FieldDeclarationSubstituted.erasedField() = getOriginal().erasedField(); 055 056 syn MethodDecl MethodDecl.erasedMethod() = this; 057 eq MethodDeclSubstituted.erasedMethod() = getOriginal().erasedMethod(); 058 eq ParMethodDecl.erasedMethod() = genericMethodDecl().erasedMethod(); 059 060 refine CodeGeneration public void VarAccess.emitStore(CodeGeneration gen) { 061 Variable v = decl(); 062 if(v instanceof FieldDeclaration) { 063 FieldDeclaration f = (FieldDeclaration)v; 064 f = f.erasedField(); 065 if(requiresAccessor()) 066 f.createAccessorWrite(fieldQualifierType()).emitInvokeMethod(gen, fieldQualifierType()); 067 else 068 f.emitStoreField(gen, fieldQualifierType()); 069 } 070 else 071 refined(gen); 072 } 073 refine CreateBCode public void VarAccess.createAssignLoadDest(CodeGeneration gen) { 074 Variable v = decl(); 075 if(v instanceof FieldDeclaration) { 076 createLoadQualifier(gen); 077 if(v.isInstanceVariable()) 078 gen.emitDup(); 079 FieldDeclaration f = (FieldDeclaration)v; 080 f = f.erasedField(); 081 if(requiresAccessor()) 082 f.createAccessor(fieldQualifierType()).emitInvokeMethod(gen, fieldQualifierType()); 083 else 084 f.emitLoadField(gen, fieldQualifierType()); 085 } 086 else 087 refined(gen); 088 } 089 090 refine CreateBCode public void VarAccess.createBCode(CodeGeneration gen) { 091 Variable v = decl(); 092 if(v instanceof FieldDeclaration) { 093 FieldDeclaration f = (FieldDeclaration)v; 094 f = f.erasedField(); 095 createLoadQualifier(gen); 096 if(f.isConstant() && (f.type().isPrimitive() || f.type().isString())) { 097 if(!f.isStatic()) 098 fieldQualifierType().emitPop(gen); 099 f.constant().createBCode(gen); 100 } 101 else if(requiresAccessor()) 102 f.createAccessor(fieldQualifierType()).emitInvokeMethod(gen, fieldQualifierType()); 103 else 104 f.emitLoadField(gen, fieldQualifierType()); 105 if(f.type() != decl().type()) 106 gen.emitCheckCast(decl().type()); 107 } 108 else 109 refined(gen); 110 } 111 112 refine CreateBCode public void MethodAccess.createBCode(CodeGeneration gen) { 113 MethodDecl decl = decl().erasedMethod(); 114 createLoadQualifier(gen); 115 116 if(decl.type().isUnknown()) { 117 System.err.println("Could not bind " + this); 118 for (int i = 0; i < getNumArg(); ++i) { 119 System.err.println("Argument " + getArg(i) + " is of type " + getArg(i).type().typeName()); 120 if(getArg(i).varDecl() != null) System.err.println(getArg(i).varDecl() + " in " + getArg(i).varDecl().hostType().typeName()); 121 } 122 if(isQualified()) 123 System.err.println("Qualifier " + qualifier() + " is of type " + qualifier().type().typeName()); 124 throw new Error("Could not bind " + this); 125 } 126 if(decl.getNumParameter() != getNumArg()) { 127 System.out.println(this + " does not have the same number of arguments as " + decl); 128 } 129 130 for (int i = 0; i < getNumArg(); ++i) { 131 getArg(i).createBCode(gen); 132 // the cast or boxing/unboxing operation must know the bound rather than the erased type 133 getArg(i).type().emitCastTo(gen, decl().getParameter(i).type()); // MethodInvocationConversion 134 } 135 if(!decl.isStatic() && isQualified() && prevExpr().isSuperAccess()) { 136 if(!hostType().instanceOf(prevExpr().type())) 137 decl().createSuperAccessor(superAccessorTarget()).emitInvokeMethod(gen, superAccessorTarget()); 138 else 139 decl.emitInvokeSpecialMethod(gen, methodQualifierType()); 140 } 141 else 142 decl.emitInvokeMethod(gen, methodQualifierType()); 143 144 if(decl.type() != decl().type()) 145 gen.emitCheckCast(decl().type()); 146 } 147 148 refine InnerClasses protected TypeDecl MethodAccess.methodQualifierType() { 149 TypeDecl typeDecl = refined(); 150 if(typeDecl == null) 151 return null; 152 typeDecl = typeDecl.erasure(); 153 MethodDecl m = decl().sourceMethodDecl(); 154 Collection methods = typeDecl.memberMethods(m.name()); 155 if(!methods.contains(decl()) && !methods.contains(m)) 156 return m.hostType(); 157 return typeDecl.erasure(); 158 } 159 160 refine InnerClasses protected TypeDecl VarAccess.fieldQualifierType() { 161 TypeDecl typeDecl = refined(); 162 return typeDecl == null ? null : typeDecl.erasure(); 163 } 164 165 public void ConstructorDeclSubstituted.emitInvokeConstructor(CodeGeneration gen) { 166 erasedConstructor().emitInvokeConstructor(gen); 167 } 168 syn ConstructorDecl ConstructorDecl.erasedConstructor() = this; 169 eq ConstructorDeclSubstituted.erasedConstructor() = getOriginal().erasedConstructor(); 170 171 172 eq TypeVariable.constantPoolName() = erasure().constantPoolName(); 173 eq ParClassDecl.constantPoolName() = genericDecl().constantPoolName(); 174 eq ParInterfaceDecl.constantPoolName() = genericDecl().constantPoolName(); 175 eq GenericClassDecl.constantPoolName() { 176 if(!isNestedType()) { 177 String packageName = packageName(); 178 if(!packageName.equals("")) { 179 packageName = packageName.replace('.', '/') + "/"; 180 } 181 return packageName + getID(); 182 } 183 else { 184 String prefix = enclosingType().constantPoolName(); 185 if(isAnonymous()) { 186 return prefix + "$" + uniqueIndex(); 187 } 188 else if(isLocalClass()) { 189 return prefix + "$" + uniqueIndex() + getID(); 190 } 191 return prefix + "$" + getID(); 192 } 193 } 194 eq GenericInterfaceDecl.constantPoolName() { 195 if(!isNestedType()) { 196 String packageName = packageName(); 197 if(!packageName.equals("")) { 198 packageName = packageName.replace('.', '/') + "/"; 199 } 200 return packageName + getID(); 201 } 202 else { 203 String prefix = enclosingType().constantPoolName(); 204 if(isAnonymous()) { 205 return prefix + "$" + uniqueIndex(); 206 } 207 else if(isLocalClass()) { 208 return prefix + "$" + uniqueIndex() + getID(); 209 } 210 return prefix + "$" + getID(); 211 } 212 } 213 214 public void BridgeMethodDecl.transformation() { } 215 public void MethodDeclSubstituted.transformation() { } 216 public void ParMethodDecl.transformation() { } 217 218 public static final int Modifiers.ACC_BRIDGE = 0x0040; 219 220 eq BridgeMethodDecl.flags() { 221 int res = super.flags(); 222 res |= Modifiers.ACC_BRIDGE; 223 res |= Modifiers.ACC_SYNTHETIC; 224 return res; 225 } 226 227 syn SimpleSet TypeDecl.bridgeCandidates(String signature) = SimpleSet.emptySet; 228 eq InterfaceDecl.bridgeCandidates(String signature) = ancestorMethods(signature); 229 eq ClassDecl.bridgeCandidates(String signature) { 230 SimpleSet set = ancestorMethods(signature); 231 for(Iterator iter = interfacesMethodsSignature(signature).iterator(); iter.hasNext(); ) 232 set = set.add(iter.next()); 233 return set; 234 } 235 236 public void MethodDecl.transformation() { 237 super.transformation(); 238 HashSet processed = new HashSet(); 239 for(Iterator iter = hostType().bridgeCandidates(signature()).iterator(); iter.hasNext(); ) { 240 MethodDecl m = (MethodDecl)iter.next(); 241 if(this.overrides(m)) { 242 MethodDecl erased = m.erasedMethod(); 243 if(!erased.signature().equals(signature()) || erased.type().erasure() != type().erasure()) { 244 StringBuffer keyBuffer = new StringBuffer(); 245 for(int i = 0; i < getNumParameter(); i++) { 246 keyBuffer.append(erased.getParameter(i).type().erasure().fullName()); 247 } 248 keyBuffer.append(erased.type().erasure().fullName()); 249 String key = keyBuffer.toString(); 250 if(!processed.contains(key)) { 251 processed.add(key); 252 253 List args = new List(); 254 List parameters = new List(); 255 for(int i = 0; i < getNumParameter(); i++) { 256 args.add(new CastExpr(getParameter(i).type().erasure().createBoundAccess(), new VarAccess("p" + i))); 257 parameters.add(new ParameterDeclaration(erased.getParameter(i).type().erasure(), "p" + i)); 258 } 259 Stmt stmt; 260 if(type().isVoid()) { 261 stmt = new ExprStmt( 262 createBoundAccess( 263 args 264 ) 265 ); 266 } 267 else { 268 stmt = new ReturnStmt( 269 createBoundAccess( 270 args 271 ) 272 ); 273 } 274 List modifiersList = new List(); 275 if(isPublic()) 276 modifiersList.add(new Modifier("public")); 277 else if(isProtected()) 278 modifiersList.add(new Modifier("protected")); 279 else if(isPrivate()) 280 modifiersList.add(new Modifier("private")); 281 MethodDecl bridge = new BridgeMethodDecl( 282 new Modifiers(modifiersList), 283 erased.type().erasure().createBoundAccess(), 284 erased.name(), 285 parameters, 286 (List)getExceptionList().fullCopy(), 287 new Opt( 288 new Block( 289 new List().add(stmt) 290 ) 291 ) 292 ); 293 hostType().addBodyDecl(bridge); 294 } 295 } 296 } 297 } 298 } 299 300 public void ParTypeDecl.transformation() { 301 } 302 303 refine Transformations public void TypeAccess.transformation() { 304 super.transformation(); 305 if(type().elementType().isNestedType() && hostType() != null) 306 hostType().addUsedNestedType(type().elementType().erasure().sourceTypeDecl()); 307 } 308 309 // add Signature Attribute 310 refine AnnotationsCodegen eq TypeDecl.attributes() { 311 Collection c = refined(); 312 if(needsSignatureAttribute()) 313 c.add(new SignatureAttribute(constantPool(), classSignature())); 314 return c; 315 } 316 317 refine AnnotationsCodegen eq MethodDecl.attributes() { 318 Collection c = refined(); 319 if(needsSignatureAttribute()) 320 c.add(new SignatureAttribute(hostType().constantPool(), methodTypeSignature())); 321 return c; 322 } 323 324 refine AnnotationsCodegen eq FieldDeclaration.attributes() { 325 Collection c = refined(); 326 if(needsSignatureAttribute()) 327 c.add(new SignatureAttribute(hostType().constantPool(), type().fieldTypeSignature())); 328 return c; 329 } 330 331 class SignatureAttribute extends Attribute { 332 public SignatureAttribute(ConstantPool cp, String signature) { 333 super(cp, "Signature"); 334 u2(cp.addUtf8(signature)); 335 } 336 } 337 338 // Determine which classes, interfaces, methods, and fields need a signature attribute 339 syn lazy boolean TypeDecl.needsSignatureAttribute() = false; 340 eq GenericClassDecl.needsSignatureAttribute() = true; 341 eq GenericInterfaceDecl.needsSignatureAttribute() = true; 342 eq ParClassDecl.needsSignatureAttribute() = true; 343 eq ParInterfaceDecl.needsSignatureAttribute() = true; 344 eq AbstractWildcardType.needsSignatureAttribute() = true; 345 eq TypeVariable.needsSignatureAttribute() = true; 346 eq ArrayDecl.needsSignatureAttribute() = elementType().needsSignatureAttribute(); 347 eq ClassDecl.needsSignatureAttribute() { 348 if(hasSuperclass() && superclass().needsSignatureAttribute()) 349 return true; 350 for(Iterator iter = interfacesIterator(); iter.hasNext(); ) 351 if(((TypeDecl)iter.next()).needsSignatureAttribute()) 352 return true; 353 return false; 354 } 355 eq InterfaceDecl.needsSignatureAttribute() { 356 for(Iterator iter = superinterfacesIterator(); iter.hasNext(); ) 357 if(((TypeDecl)iter.next()).needsSignatureAttribute()) 358 return true; 359 return false; 360 } 361 362 syn boolean BodyDecl.needsSignatureAttribute() = false; 363 syn boolean MethodDecl.needsSignatureAttribute() { 364 if(type().needsSignatureAttribute()) 365 return true; 366 for(int i = 0; i < getNumParameter(); i++) 367 if(getParameter(i).type().needsSignatureAttribute()) 368 return true; 369 return false; 370 } 371 372 eq GenericMethodDecl.needsSignatureAttribute() = true; 373 syn boolean ConstructorDecl.needsSignatureAttribute() { 374 for(int i = 0; i < getNumParameter(); i++) 375 if(getParameter(i).type().needsSignatureAttribute()) 376 return true; 377 return false; 378 } 379 eq GenericConstructorDecl.needsSignatureAttribute() = true; 380 381 eq FieldDeclaration.needsSignatureAttribute() = type().needsSignatureAttribute(); 382 383 // compute the signature string used for the signature attribute 384 syn lazy String TypeDecl.classSignature() = ""; 385 eq ClassDecl.classSignature() { 386 StringBuffer buf = new StringBuffer(); 387 // SuperclassSignature 388 if(hasSuperclass()) 389 buf.append(superclass().classTypeSignature()); 390 // SuperinterfaceSignature* 391 for(Iterator iter = interfacesIterator(); iter.hasNext(); ) 392 buf.append(((TypeDecl)iter.next()).classTypeSignature()); 393 return buf.toString(); 394 } 395 eq InterfaceDecl.classSignature() { 396 StringBuffer buf = new StringBuffer(); 397 // SuperclassSignature 398 buf.append(typeObject().classTypeSignature()); 399 // SuperinterfaceSignature* 400 for(Iterator iter = superinterfacesIterator(); iter.hasNext(); ) 401 buf.append(((TypeDecl)iter.next()).classTypeSignature()); 402 return buf.toString(); 403 } 404 eq GenericClassDecl.classSignature() { 405 StringBuffer buf = new StringBuffer(); 406 // FormalTypeParameters 407 buf.append("<"); 408 for(int i = 0; i < getNumTypeParameter(); i++) 409 buf.append(getTypeParameter(i).formalTypeParameter()); 410 buf.append(">"); 411 buf.append(super.classSignature()); 412 return buf.toString(); 413 } 414 eq GenericInterfaceDecl.classSignature() { 415 StringBuffer buf = new StringBuffer(); 416 // FormalTypeParameters 417 buf.append("<"); 418 for(int i = 0; i < getNumTypeParameter(); i++) 419 buf.append(getTypeParameter(i).formalTypeParameter()); 420 buf.append(">"); 421 buf.append(super.classSignature()); 422 return buf.toString(); 423 } 424 425 // FormalTypeParameter 426 syn String TypeVariable.formalTypeParameter() { 427 StringBuffer buf = new StringBuffer(); 428 // Identifier 429 buf.append(name()); 430 buf.append(":"); 431 if(getNumTypeBound() > 0) { 432 // ClassBound InterfaceBound* 433 if(getTypeBound(0).type().isClassDecl()) 434 buf.append(getTypeBound(0).type().fieldTypeSignature()); 435 else 436 buf.append(":" + getTypeBound(0).type().fieldTypeSignature()); 437 for(int i = 1; i < getNumTypeBound(); i++) 438 buf.append(":" + getTypeBound(i).type().fieldTypeSignature()); 439 } 440 return buf.toString(); 441 } 442 443 syn lazy String TypeDecl.fieldTypeSignature() = classTypeSignature(); 444 eq ArrayDecl.fieldTypeSignature() = "[" + componentType().fieldTypeSignature(); 445 eq TypeVariable.fieldTypeSignature() = classTypeSignature(); 446 eq WildcardType.fieldTypeSignature() = "*"; 447 eq WildcardExtendsType.fieldTypeSignature() = "+" + extendsType().fieldTypeSignature(); 448 eq WildcardSuperType.fieldTypeSignature() = "-" + superType().fieldTypeSignature(); 449 eq PrimitiveType.fieldTypeSignature() = classTypeSignature(); 450 eq VoidType.fieldTypeSignature() = classTypeSignature(); 451 452 syn lazy String TypeDecl.classTypeSignature() = "L" + classTypeSignatureContents() + ";"; 453 eq ArrayDecl.classTypeSignature() = "[" + componentType().classTypeSignature(); 454 eq TypeVariable.classTypeSignature() = "T" + name() + ";"; 455 eq PrimitiveType.classTypeSignature() = typeDescriptor(); 456 eq VoidType.classTypeSignature() = typeDescriptor(); 457 458 syn String TypeDecl.classTypeSignatureContents() { 459 StringBuffer buf = new StringBuffer(); 460 if(isTopLevelType()) { 461 if(!packageName().equals("")) 462 buf.append(packageName().replace('.', '/') + "/"); 463 } 464 else 465 buf.append(enclosingType().classTypeSignatureContents() + "."); 466 buf.append(name()); 467 buf.append(typeArgumentsOpt()); 468 return buf.toString(); 469 } 470 syn String TypeDecl.typeArgumentsOpt() = ""; 471 eq ParTypeDecl.typeArgumentsOpt() { 472 StringBuffer buf = new StringBuffer(); 473 buf.append("<"); 474 for(int i = 0; i < getNumArgument(); i++) 475 buf.append(getArgument(i).type().fieldTypeSignature()); 476 buf.append(">"); 477 return buf.toString(); 478 } 479 eq RawClassDecl.typeArgumentsOpt() = ""; 480 eq RawInterfaceDecl.typeArgumentsOpt() = ""; 481 482 syn String MethodDecl.methodTypeSignature() { 483 StringBuffer buf = new StringBuffer(); 484 buf.append("("); 485 for(int i = 0; i < getNumParameter(); i++) 486 buf.append(getParameter(i).type().classTypeSignature()); 487 buf.append(")"); 488 buf.append(type().classTypeSignature()); 489 for(int i = 0; i < getNumException(); i++) 490 buf.append("^" + getException(i).type().classTypeSignature()); 491 return buf.toString(); 492 } 493 eq GenericMethodDecl.methodTypeSignature() { 494 StringBuffer buf = new StringBuffer(); 495 buf.append("<"); 496 for(int i = 0; i < getNumTypeParameter(); i++) { 497 TypeVariable param = getTypeParameter(i); 498 buf.append(param.getID() + ":" + param.classBound() + param.interfaceBounds()); 499 } 500 buf.append(">"); 501 buf.append(super.methodTypeSignature()); 502 return buf.toString(); 503 } 504 syn lazy String TypeVariable.classBound() { 505 if (getNumTypeBound() > 0) { 506 return getTypeBound(0).type().fieldTypeSignature(); 507 } 508 return ""; 509 } 510 syn lazy String TypeVariable.interfaceBounds() { 511 StringBuffer buf = new StringBuffer(); 512 for (int i = 1; i < getNumTypeBound(); ++i) { 513 buf.append(":"); 514 buf.append(getTypeBound(i).type().fieldTypeSignature()); 515 } 516 return buf.toString(); 517 } 518 }