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