001 /* This file was generated with JastAdd2 (http://jastadd.org) version 2.1.13-12-g880e696 */ 002 package org.extendj.ast; 003 004 import java.util.HashSet; 005 import java.io.File; 006 import java.util.Set; 007 import java.util.Collections; 008 import java.util.Collection; 009 import java.util.ArrayList; 010 import beaver.*; 011 import java.util.*; 012 import java.io.ByteArrayOutputStream; 013 import java.io.PrintStream; 014 import java.lang.reflect.InvocationTargetException; 015 import java.lang.reflect.Method; 016 import org.jastadd.util.*; 017 import java.util.zip.*; 018 import java.io.*; 019 import org.jastadd.util.PrettyPrintable; 020 import org.jastadd.util.PrettyPrinter; 021 import java.io.FileNotFoundException; 022 import java.io.BufferedInputStream; 023 import java.io.DataInputStream; 024 /** 025 * Type access for a generic class with an empty type parameter list. 026 * @ast node 027 * @declaredat /home/jesper/git/extendj/java7/grammar/Diamond.ast:4 028 * @production DiamondAccess : {@link Access} ::= <span class="component">TypeAccess:{@link Access}</span>; 029 030 */ 031 public class DiamondAccess extends Access implements Cloneable { 032 /** 033 * @aspect Diamond 034 * @declaredat /home/jesper/git/extendj/java7/frontend/Diamond.jrag:94 035 */ 036 protected static SimpleSet mostSpecific(SimpleSet maxSpecific, MethodDecl decl) { 037 if (maxSpecific.isEmpty()) { 038 maxSpecific = maxSpecific.add(decl); 039 } else { 040 MethodDecl other = (MethodDecl) maxSpecific.iterator().next(); 041 if (decl.moreSpecificThan(other)) { 042 maxSpecific = decl; 043 } else if (!other.moreSpecificThan(decl)) { 044 maxSpecific = maxSpecific.add(decl); 045 } 046 } 047 return maxSpecific; 048 } 049 /** 050 * Choose a constructor for the diamond operator using placeholder 051 * methods. 052 * @aspect Diamond 053 * @declaredat /home/jesper/git/extendj/java7/frontend/Diamond.jrag:112 054 */ 055 protected SimpleSet chooseConstructor() { 056 ClassInstanceExpr instanceExpr = getClassInstanceExpr(); 057 TypeDecl type = getTypeAccess().type(); 058 059 assert instanceExpr != null; 060 assert type instanceof ParClassDecl; 061 062 GenericClassDecl genericType = (GenericClassDecl) ((ParClassDecl) type).genericDecl(); 063 064 List<StandInMethodDecl> placeholderMethods = genericType.getStandInMethodList(); 065 066 SimpleSet maxSpecific = SimpleSet.emptySet; 067 Collection<MethodDecl> potentiallyApplicable = potentiallyApplicable(placeholderMethods); 068 for (MethodDecl candidate : potentiallyApplicable) { 069 if (applicableBySubtyping(instanceExpr, candidate) 070 || applicableByMethodInvocationConversion(instanceExpr, candidate) 071 || applicableByVariableArity(instanceExpr, candidate)) { 072 maxSpecific = mostSpecific(maxSpecific, candidate); 073 } 074 } 075 return maxSpecific; 076 } 077 /** 078 * Select potentially applicable method declarations 079 * from a set of candidates. 080 * Type inference is applied to the (potentially) applicable candidates. 081 * @aspect Diamond 082 * @declaredat /home/jesper/git/extendj/java7/frontend/Diamond.jrag:238 083 */ 084 protected Collection<MethodDecl> potentiallyApplicable( 085 List<StandInMethodDecl> candidates) { 086 Collection<MethodDecl> potentiallyApplicable = new LinkedList<MethodDecl>(); 087 for (GenericMethodDecl candidate : candidates) { 088 if (potentiallyApplicable(candidate)) { 089 MethodDecl decl = candidate.lookupParMethodDecl( 090 inferTypeArguments( 091 candidate.type(), 092 candidate.getParameterList(), 093 getClassInstanceExpr().getArgList(), 094 candidate.getTypeParameterList())); 095 potentiallyApplicable.add(decl); 096 } 097 } 098 return potentiallyApplicable; 099 } 100 /** 101 * Test if a method is applicable for this diamond access. 102 * @param candidate candidate method 103 * @return false if the candidate method is not applicable. 104 * @aspect Diamond 105 * @declaredat /home/jesper/git/extendj/java7/frontend/Diamond.jrag:260 106 */ 107 protected boolean potentiallyApplicable( 108 GenericMethodDecl candidate) { 109 if (candidate.isVariableArity() && !(getClassInstanceExpr().arity() >= candidate.arity()-1)) { 110 return false; 111 } 112 if (!candidate.isVariableArity() && !(getClassInstanceExpr().arity() == candidate.arity())) { 113 return false; 114 } 115 116 java.util.List<TypeDecl> typeArgs = inferTypeArguments( 117 candidate.type(), 118 candidate.getParameterList(), 119 getClassInstanceExpr().getArgList(), 120 candidate.getTypeParameterList()); 121 Parameterization par = new SimpleParameterization(candidate.getTypeParameterList(), typeArgs); 122 if (typeArgs.size() != 0) { 123 if (candidate.getNumTypeParameter() != typeArgs.size()) { 124 return false; 125 } 126 for (int i = 0; i < candidate.getNumTypeParameter(); i++) { 127 if (!typeArgs.get(i).withinBounds(candidate.original().getTypeParameter(i), par)) { 128 return false; 129 } 130 } 131 } 132 return true; 133 } 134 /** 135 * @return true if the method is applicable by subtyping 136 * @aspect Diamond 137 * @declaredat /home/jesper/git/extendj/java7/frontend/Diamond.jrag:291 138 */ 139 protected boolean applicableBySubtyping(ClassInstanceExpr expr, MethodDecl method) { 140 if (method.getNumParameter() != expr.getNumArg()) { 141 return false; 142 } 143 for (int i = 0; i < method.getNumParameter(); i++) { 144 if (!expr.getArg(i).type().instanceOf(method.getParameter(i).type())) { 145 return false; 146 } 147 } 148 return true; 149 } 150 /** 151 * @return true if the method is applicable by method invocation conversion 152 * @aspect Diamond 153 * @declaredat /home/jesper/git/extendj/java7/frontend/Diamond.jrag:306 154 */ 155 protected boolean applicableByMethodInvocationConversion( 156 ClassInstanceExpr expr, MethodDecl method) { 157 if (method.getNumParameter() != expr.getNumArg()) { 158 return false; 159 } 160 for (int i = 0; i < method.getNumParameter(); i++) { 161 if (!expr.getArg(i).type().methodInvocationConversionTo( 162 method.getParameter(i).type())) { 163 return false; 164 } 165 } 166 return true; 167 } 168 /** 169 * @return true if the method is applicable by variable arity 170 * @aspect Diamond 171 * @declaredat /home/jesper/git/extendj/java7/frontend/Diamond.jrag:323 172 */ 173 protected boolean applicableByVariableArity( 174 ClassInstanceExpr expr, MethodDecl method) { 175 for (int i = 0; i < method.getNumParameter() - 1; i++) { 176 if (!expr.getArg(i).type().methodInvocationConversionTo( 177 method.getParameter(i).type())) { 178 return false; 179 } 180 } 181 for (int i = method.getNumParameter() - 1; i < expr.getNumArg(); i++) { 182 if (!expr.getArg(i).type().methodInvocationConversionTo( 183 method.lastParameter().type().componentType())) { 184 return false; 185 } 186 } 187 return true; 188 } 189 /** 190 * Checks if this diamond access is legal. 191 * The diamond access is not legal if it either is part of an inner class 192 * declaration, if it is used to access a non-generic type, or if it is 193 * part of a call to a generic constructor with explicit type arguments. 194 * @aspect Diamond 195 * @declaredat /home/jesper/git/extendj/java7/frontend/Diamond.jrag:435 196 */ 197 public void typeCheck() { 198 if (isAnonymousDecl()) { 199 error("the diamond operator can not be used with anonymous classes"); 200 } 201 if (isExplicitGenericConstructorAccess()) { 202 error("the diamond operator may not be used with generic " 203 + "constructors with explicit type parameters"); 204 } 205 if (getClassInstanceExpr() == null) { 206 error("the diamond operator can only be used in class instance expressions"); 207 } 208 if (!(getTypeAccess().type() instanceof ParClassDecl)) { 209 error("the diamond operator can only be used to instantiate generic classes"); 210 } 211 } 212 /** 213 * @aspect Java7PrettyPrint 214 * @declaredat /home/jesper/git/extendj/java7/frontend/PrettyPrint.jadd:35 215 */ 216 public void prettyPrint(PrettyPrinter out) { 217 out.print(getTypeAccess()); 218 out.print("<>"); 219 } 220 /** 221 * @declaredat ASTNode:1 222 */ 223 public DiamondAccess() { 224 super(); 225 } 226 /** 227 * Initializes the child array to the correct size. 228 * Initializes List and Opt nta children. 229 * @apilevel internal 230 * @ast method 231 * @declaredat ASTNode:10 232 */ 233 public void init$Children() { 234 children = new ASTNode[1]; 235 } 236 /** 237 * @declaredat ASTNode:13 238 */ 239 public DiamondAccess(Access p0) { 240 setChild(p0, 0); 241 } 242 /** 243 * @apilevel low-level 244 * @declaredat ASTNode:19 245 */ 246 protected int numChildren() { 247 return 1; 248 } 249 /** 250 * @apilevel internal 251 * @declaredat ASTNode:25 252 */ 253 public boolean mayHaveRewrite() { 254 return false; 255 } 256 /** 257 * @apilevel internal 258 * @declaredat ASTNode:31 259 */ 260 public void flushAttrCache() { 261 super.flushAttrCache(); 262 type_reset(); 263 } 264 /** 265 * @apilevel internal 266 * @declaredat ASTNode:38 267 */ 268 public void flushCollectionCache() { 269 super.flushCollectionCache(); 270 } 271 /** 272 * @apilevel internal 273 * @declaredat ASTNode:44 274 */ 275 public void flushRewriteCache() { 276 super.flushRewriteCache(); 277 } 278 /** 279 * @apilevel internal 280 * @declaredat ASTNode:50 281 */ 282 public DiamondAccess clone() throws CloneNotSupportedException { 283 DiamondAccess node = (DiamondAccess) super.clone(); 284 return node; 285 } 286 /** 287 * @apilevel internal 288 * @declaredat ASTNode:57 289 */ 290 public DiamondAccess copy() { 291 try { 292 DiamondAccess node = (DiamondAccess) clone(); 293 node.parent = null; 294 if (children != null) { 295 node.children = (ASTNode[]) children.clone(); 296 } 297 return node; 298 } catch (CloneNotSupportedException e) { 299 throw new Error("Error: clone not supported for " + getClass().getName()); 300 } 301 } 302 /** 303 * Create a deep copy of the AST subtree at this node. 304 * The copy is dangling, i.e. has no parent. 305 * @return dangling copy of the subtree at this node 306 * @apilevel low-level 307 * @deprecated Please use treeCopy or treeCopyNoTransform instead 308 * @declaredat ASTNode:76 309 */ 310 @Deprecated 311 public DiamondAccess fullCopy() { 312 return treeCopyNoTransform(); 313 } 314 /** 315 * Create a deep copy of the AST subtree at this node. 316 * The copy is dangling, i.e. has no parent. 317 * @return dangling copy of the subtree at this node 318 * @apilevel low-level 319 * @declaredat ASTNode:86 320 */ 321 public DiamondAccess treeCopyNoTransform() { 322 DiamondAccess tree = (DiamondAccess) copy(); 323 if (children != null) { 324 for (int i = 0; i < children.length; ++i) { 325 ASTNode child = (ASTNode) children[i]; 326 if (child != null) { 327 child = child.treeCopyNoTransform(); 328 tree.setChild(child, i); 329 } 330 } 331 } 332 return tree; 333 } 334 /** 335 * Create a deep copy of the AST subtree at this node. 336 * The subtree of this node is traversed to trigger rewrites before copy. 337 * The copy is dangling, i.e. has no parent. 338 * @return dangling copy of the subtree at this node 339 * @apilevel low-level 340 * @declaredat ASTNode:106 341 */ 342 public DiamondAccess treeCopy() { 343 doFullTraversal(); 344 return treeCopyNoTransform(); 345 } 346 /** 347 * @apilevel internal 348 * @declaredat ASTNode:113 349 */ 350 protected boolean is$Equal(ASTNode node) { 351 return super.is$Equal(node); 352 } 353 /** 354 * Replaces the TypeAccess child. 355 * @param node The new node to replace the TypeAccess child. 356 * @apilevel high-level 357 */ 358 public void setTypeAccess(Access node) { 359 setChild(node, 0); 360 } 361 /** 362 * Retrieves the TypeAccess child. 363 * @return The current node used as the TypeAccess child. 364 * @apilevel high-level 365 */ 366 @ASTNodeAnnotation.Child(name="TypeAccess") 367 public Access getTypeAccess() { 368 return (Access) getChild(0); 369 } 370 /** 371 * Retrieves the TypeAccess child. 372 * <p><em>This method does not invoke AST transformations.</em></p> 373 * @return The current node used as the TypeAccess child. 374 * @apilevel low-level 375 */ 376 public Access getTypeAccessNoTransform() { 377 return (Access) getChildNoTransform(0); 378 } 379 /** 380 * @apilevel internal 381 */ 382 protected boolean type_computed = false; 383 /** 384 * @apilevel internal 385 */ 386 protected TypeDecl type_value; 387 /** 388 * @apilevel internal 389 */ 390 private void type_reset() { 391 type_computed = false; 392 type_value = null; 393 } 394 /** 395 * @attribute syn 396 * @aspect TypeAnalysis 397 * @declaredat /home/jesper/git/extendj/java4/frontend/TypeAnalysis.jrag:302 398 */ 399 @ASTNodeAnnotation.Attribute 400 public TypeDecl type() { 401 ASTNode$State state = state(); 402 if (type_computed) { 403 return type_value; 404 } 405 boolean intermediate = state.INTERMEDIATE_VALUE; 406 state.INTERMEDIATE_VALUE = false; 407 int num = state.boundariesCrossed; 408 boolean isFinal = this.is$Final(); 409 type_value = type_compute(); 410 if (isFinal && num == state().boundariesCrossed) { 411 type_computed = true; 412 } else { 413 } 414 state.INTERMEDIATE_VALUE |= intermediate; 415 416 return type_value; 417 } 418 /** 419 * @apilevel internal 420 */ 421 private TypeDecl type_compute() { 422 TypeDecl accessType = getTypeAccess().type(); 423 424 if (isAnonymousDecl()) { 425 return accessType; 426 } 427 428 if (getClassInstanceExpr() == null) { 429 // It is an error if the DiamondAccess does not occurr 430 // within a class instance creation expression, but this 431 // error is handled in typeCheck. 432 return accessType; 433 } 434 435 if (!(accessType instanceof ParClassDecl)) { 436 // It is an error if the TypeDecl of a DiamondAccess is not 437 // a generic type, but this error is handled in typeCheck. 438 return accessType; 439 } 440 441 SimpleSet maxSpecific = chooseConstructor(); 442 443 if (maxSpecific.isEmpty()) { 444 return getTypeAccess().type(); 445 } 446 447 MethodDecl constructor = (MethodDecl) maxSpecific.iterator().next(); 448 return constructor.type(); 449 } 450 /** 451 * @attribute syn 452 * @aspect Diamond 453 * @declaredat /home/jesper/git/extendj/java7/frontend/Diamond.jrag:87 454 */ 455 @ASTNodeAnnotation.Attribute 456 public boolean isDiamond() { 457 boolean isDiamond_value = true; 458 459 return isDiamond_value; 460 } 461 /** 462 * @attribute inh 463 * @aspect Diamond 464 * @declaredat /home/jesper/git/extendj/java7/frontend/Diamond.jrag:90 465 */ 466 /** 467 * @attribute inh 468 * @aspect Diamond 469 * @declaredat /home/jesper/git/extendj/java7/frontend/Diamond.jrag:90 470 */ 471 @ASTNodeAnnotation.Attribute 472 public ClassInstanceExpr getClassInstanceExpr() { 473 ClassInstanceExpr getClassInstanceExpr_value = getParent().Define_getClassInstanceExpr(this, null); 474 475 return getClassInstanceExpr_value; 476 } 477 /** 478 * @return true if this access is part of an anonymous class declaration 479 * @attribute inh 480 * @aspect Diamond 481 * @declaredat /home/jesper/git/extendj/java7/frontend/Diamond.jrag:401 482 */ 483 /** 484 * @return true if this access is part of an anonymous class declaration 485 * @attribute inh 486 * @aspect Diamond 487 * @declaredat /home/jesper/git/extendj/java7/frontend/Diamond.jrag:401 488 */ 489 @ASTNodeAnnotation.Attribute 490 public boolean isAnonymousDecl() { 491 boolean isAnonymousDecl_value = getParent().Define_isAnonymousDecl(this, null); 492 493 return isAnonymousDecl_value; 494 } 495 /** 496 * @return true if the Access is part of a generic constructor invocation 497 * with explicit type arguments 498 * @attribute inh 499 * @aspect Diamond 500 * @declaredat /home/jesper/git/extendj/java7/frontend/Diamond.jrag:417 501 */ 502 /** 503 * @return true if the Access is part of a generic constructor invocation 504 * with explicit type arguments 505 * @attribute inh 506 * @aspect Diamond 507 * @declaredat /home/jesper/git/extendj/java7/frontend/Diamond.jrag:417 508 */ 509 @ASTNodeAnnotation.Attribute 510 public boolean isExplicitGenericConstructorAccess() { 511 boolean isExplicitGenericConstructorAccess_value = getParent().Define_isExplicitGenericConstructorAccess(this, null); 512 513 return isExplicitGenericConstructorAccess_value; 514 } 515 /** 516 * @apilevel internal 517 */ 518 public ASTNode rewriteTo() { 519 return super.rewriteTo(); 520 } 521 }