1 package polyglot.ext.jl.ast; 2 3 import java.util.*; 4 5 import polyglot.ast.*; 6 import polyglot.frontend.Pass; 7 import polyglot.frontend.Job; 8 import polyglot.types.*; 9 import polyglot.util.*; 10 import polyglot.visit.*; 11 12 19 public class New_c extends Expr_c implements New 20 { 21 protected Expr qualifier; 22 protected TypeNode tn; 23 protected List arguments; 24 protected ClassBody body; 25 protected ConstructorInstance ci; 26 protected ParsedClassType anonType; 27 28 public New_c(Position pos, Expr qualifier, TypeNode tn, List arguments, ClassBody body) { 29 super(pos); 30 this.qualifier = qualifier; 31 this.tn = tn; 32 this.arguments = TypedList.copyAndCheck(arguments, Expr.class, true); 33 this.body = body; 34 } 35 36 37 public Expr qualifier() { 38 return this.qualifier; 39 } 40 41 42 public New qualifier(Expr qualifier) { 43 New_c n = (New_c) copy(); 44 n.qualifier = qualifier; 45 return n; 46 } 47 48 49 public TypeNode objectType() { 50 return this.tn; 51 } 52 53 54 public New objectType(TypeNode tn) { 55 New_c n = (New_c) copy(); 56 n.tn = tn; 57 return n; 58 } 59 60 public ParsedClassType anonType() { 61 return this.anonType; 62 } 63 64 public New anonType(ParsedClassType anonType) { 65 New_c n = (New_c) copy(); 66 n.anonType = anonType; 67 return n; 68 } 69 70 public ProcedureInstance procedureInstance() { 71 return constructorInstance(); 72 } 73 74 public ConstructorInstance constructorInstance() { 75 return this.ci; 76 } 77 78 public New constructorInstance(ConstructorInstance ci) { 79 New_c n = (New_c) copy(); 80 n.ci = ci; 81 return n; 82 } 83 84 public List arguments() { 85 return this.arguments; 86 } 87 88 public ProcedureCall arguments(List arguments) { 89 New_c n = (New_c) copy(); 90 n.arguments = TypedList.copyAndCheck(arguments, Expr.class, true); 91 return n; 92 } 93 94 public ClassBody body() { 95 return this.body; 96 } 97 98 public New body(ClassBody body) { 99 New_c n = (New_c) copy(); 100 n.body = body; 101 return n; 102 } 103 104 105 protected New_c reconstruct(Expr qualifier, TypeNode tn, List arguments, ClassBody body) { 106 if (qualifier != this.qualifier || tn != this.tn || ! CollectionUtil.equals(arguments, this.arguments) || body != this.body) { 107 New_c n = (New_c) copy(); 108 n.tn = tn; 109 n.qualifier = qualifier; 110 n.arguments = TypedList.copyAndCheck(arguments, Expr.class, true); 111 n.body = body; 112 return n; 113 } 114 115 return this; 116 } 117 118 119 public Node visitChildren(NodeVisitor v) { 120 Expr qualifier = (Expr) visitChild(this.qualifier, v); 121 TypeNode tn = (TypeNode) visitChild(this.tn, v); 122 List arguments = visitList(this.arguments, v); 123 ClassBody body = (ClassBody) visitChild(this.body, v); 124 return reconstruct(qualifier, tn, arguments, body); 125 } 126 127 public Context enterScope(Node child, Context c) { 128 if (child == body && anonType != null && body != null) { 129 c = c.pushClass(anonType, anonType); 130 } 131 return super.enterScope(child, c); 132 } 133 134 public NodeVisitor buildTypesEnter(TypeBuilder tb) throws SemanticException { 135 if (body != null) { 136 return tb.bypass(body); 143 } 144 145 146 return tb; 147 } 148 149 public Node buildTypes(TypeBuilder tb) throws SemanticException { 150 New_c n = this; 151 152 if (n.body() != null) { 153 TypeBuilder bodyTB = (TypeBuilder)tb.visitChildren(); 156 157 bodyTB = bodyTB.pushAnonClass(position()); 159 160 n = (New_c) n.body((ClassBody)n.body().visit(bodyTB)); 161 ParsedClassType type = (ParsedClassType) bodyTB.currentClass(); 162 n = (New_c) n.anonType(type); 163 } 164 165 TypeSystem ts = tb.typeSystem(); 166 167 List l = new ArrayList(n.arguments.size()); 168 for (int i = 0; i < n.arguments.size(); i++) { 169 l.add(ts.unknownType(position())); 170 } 171 172 ConstructorInstance ci = ts.constructorInstance(position(), ts.Object(), 173 Flags.NONE, l, 174 Collections.EMPTY_LIST); 175 n = (New_c) n.constructorInstance(ci); 176 177 return n.type(ts.unknownType(position())); 178 } 179 180 public NodeVisitor disambiguateEnter(AmbiguityRemover ar) 181 throws SemanticException 182 { 183 if (qualifier != null) { 188 ar = (AmbiguityRemover) ar.bypass(tn); 189 } 190 191 if (body != null) { 192 ar = (AmbiguityRemover) ar.bypass(body); 193 } 194 195 return ar; 196 } 197 198 public Node disambiguate(AmbiguityRemover ar) throws SemanticException { 199 if (ar.kind() != AmbiguityRemover.ALL) { 200 return this; 201 } 202 203 if (qualifier == null) { 204 ClassType ct = tn.type().toClass(); 205 206 if (! ct.isMember() || ct.flags().isStatic()) { 207 return this; 208 } 209 210 NodeFactory nf = ar.nodeFactory(); 213 TypeSystem ts = ar.typeSystem(); 214 Context c = ar.context(); 215 216 Type outer = null; 219 220 String name = ct.name(); 221 ClassType t = c.currentClass(); 222 223 if (t == anonType) { 225 t = t.outer(); 226 } 227 228 while (t != null) { 229 try { 230 t = ts.staticTarget(t).toClass(); 232 ClassType mt = ts.findMemberClass(t, name, c.currentClass()); 233 234 if (ts.equals(mt, ct)) { 235 outer = t; 236 break; 237 } 238 } 239 catch (SemanticException e) { 240 } 241 242 t = t.outer(); 243 } 244 245 if (outer == null) { 246 throw new SemanticException("Could not find non-static member class \"" + 247 name + "\".", position()); 248 } 249 250 Expr q; 252 253 if (outer.equals(c.currentClass())) { 254 q = nf.This(position()); 255 } 256 else { 257 q = nf.This(position(), 258 nf.CanonicalTypeNode(position(), 259 outer)); 260 } 261 262 return qualifier(q); 263 } 264 265 return this; 266 } 267 268 public NodeVisitor typeCheckEnter(TypeChecker tc) throws SemanticException { 269 if (qualifier != null) { 270 tc = (TypeChecker) tc.bypass(tn); 271 } 272 273 if (body != null) { 274 tc = (TypeChecker) tc.bypass(body); 275 } 276 277 return tc; 278 } 279 280 public Node typeCheck(TypeChecker tc) throws SemanticException { 281 New_c n = this; 282 283 if (qualifier != null) { 284 286 Type qt = qualifier.type(); 288 289 if (! qt.isClass()) { 290 throw new SemanticException( 291 "Cannot instantiate member class of a non-class type.", 292 qualifier.position()); 293 } 294 295 TypeNode tn = disambiguateTypeNode(tc, qt.toClass()); 297 ClassType ct = tn.type().toClass(); 298 299 307 308 if (! ct.isInnerClass()) { 311 throw new SemanticException( 312 "Cannot provide a containing instance for non-inner class " + 313 ct.fullName() + ".", qualifier.position()); 314 } 315 316 n = (New_c) n.objectType(tn); 317 } 318 else { 319 ClassType ct = tn.type().toClass(); 320 321 if (ct.isMember()) { 322 for (ClassType t = ct; t.isMember(); t = t.outer()) { 323 if (! t.flags().isStatic()) { 324 throw new SemanticException( 325 "Cannot allocate non-static member class \"" + 326 t + "\".", position()); 327 } 328 } 329 } 330 } 331 332 return n.typeCheckEpilogue(tc); 333 } 334 335 protected Node typeCheckEpilogue(TypeChecker tc) throws SemanticException { 336 TypeSystem ts = tc.typeSystem(); 337 338 List argTypes = new ArrayList(arguments.size()); 339 340 for (Iterator i = this.arguments.iterator(); i.hasNext(); ) { 341 Expr e = (Expr) i.next(); 342 argTypes.add(e.type()); 343 } 344 345 ClassType ct = tn.type().toClass(); 346 347 if (this.body == null) { 348 if (ct.flags().isInterface()) { 349 throw new SemanticException( 350 "Cannot instantiate an interface.", position()); 351 } 352 353 if (ct.flags().isAbstract()) { 354 throw new SemanticException( 355 "Cannot instantiate an abstract class.", position()); 356 } 357 } 358 else { 359 if (ct.flags().isFinal()) { 360 throw new SemanticException( 361 "Cannot create an anonymous subclass of a final class.", 362 position()); 363 } 364 365 if (ct.flags().isInterface() && ! arguments.isEmpty()) { 366 throw new SemanticException( 367 "Cannot pass arguments to an anonymous class that " + 368 "implements an interface.", 369 ((Expr) arguments.get(0)).position()); 370 } 371 } 372 373 374 if (! ct.flags().isInterface()) { 375 Context c = tc.context(); 376 if (body != null) { 377 380 anonType.superType(ct); 382 383 c = c.pushClass(anonType, anonType); 384 } 385 ci = ts.findConstructor(ct, argTypes, c.currentClass()); 386 } 387 else { 388 ci = ts.defaultConstructor(position(), ct); 389 } 390 391 New_c n = (New_c) this.constructorInstance(ci).type(ct); 392 393 if (n.body == null) { 394 return n; 395 } 396 397 400 if (! ct.flags().isInterface()) { 401 anonType.superType(ct); 402 } 403 else { 404 anonType.superType(ts.Object()); 405 anonType.addInterface(ct); 406 } 407 408 n = (New_c)n.type(anonType); 410 411 ClassBody body = n.typeCheckBody(tc, ct); 413 414 return n.body(body); 415 } 416 417 protected TypeNode partialDisambTypeNode(TypeNode tn, TypeChecker tc, ClassType outer) throws SemanticException 418 { 419 426 if (tn instanceof CanonicalTypeNode) { 427 return tn; 428 } 429 430 String name = null; 431 432 if (tn instanceof AmbTypeNode && ((AmbTypeNode) tn).qual() == null) { 433 name = ((AmbTypeNode) tn).name(); 434 } 435 else { 436 throw new SemanticException( 437 "Cannot instantiate an member class.", 438 tn.position()); 439 } 440 441 TypeSystem ts = tc.typeSystem(); 442 NodeFactory nf = tc.nodeFactory(); 443 Context c = tc.context(); 444 445 ClassType ct = ts.findMemberClass(outer, name, c.currentClass()); 446 return nf.CanonicalTypeNode(tn.position(), ct); 447 } 448 449 protected TypeNode disambiguateTypeNode(TypeChecker tc, ClassType ct) 450 throws SemanticException 451 { 452 TypeNode tn = this.partialDisambTypeNode(this.tn, tc, ct); 453 454 if (tn instanceof CanonicalTypeNode) { 455 return tn; 456 } 457 458 Job sj = tc.job().spawn(tc.context(), tn, 460 Pass.CLEAN_SUPER, Pass.DISAM_ALL); 461 462 if (! sj.status()) { 463 if (! sj.reportedErrors()) { 464 throw new SemanticException("Could not disambiguate type.", 465 this.tn.position()); 466 } 467 throw new SemanticException(); 468 } 469 470 tn = (TypeNode) sj.ast(); 471 472 return (TypeNode) visitChild(tn, tc); 474 } 475 476 protected ClassBody typeCheckBody(TypeChecker tc, ClassType superType) 477 throws SemanticException 478 { 479 Context bodyCtxt = tc.context().pushClass(anonType, anonType); 480 Job sj = tc.job().spawn(bodyCtxt, body, 481 Pass.CLEAN_SUPER, Pass.DISAM_ALL); 482 483 if (! sj.status()) { 484 if (! sj.reportedErrors()) { 485 throw new SemanticException("Could not disambiguate body of " + 486 "anonymous " + 487 (superType.flags().isInterface() ? 488 "implementor" : "subclass") + 489 " of \"" + superType + "\"."); 490 } 491 throw new SemanticException(); 492 } 493 494 ClassBody b = (ClassBody) sj.ast(); 495 496 TypeChecker bodyTC = (TypeChecker)tc.context(bodyCtxt); 498 b = (ClassBody) visitChild(b, bodyTC.visitChildren()); 499 500 bodyTC.typeSystem().checkClassConformance(anonType()); 502 503 return b; 504 } 505 506 public Type childExpectedType(Expr child, AscriptionVisitor av) { 507 if (child == qualifier) { 508 ReferenceType t = ci.container(); 509 510 if (t.isClass() && t.toClass().isMember()) { 511 t = t.toClass().container(); 512 return t; 513 } 514 515 return child.type(); 516 } 517 518 Iterator i = this.arguments.iterator(); 519 Iterator j = ci.formalTypes().iterator(); 520 521 while (i.hasNext() && j.hasNext()) { 522 Expr e = (Expr) i.next(); 523 Type t = (Type) j.next(); 524 525 if (e == child) { 526 return t; 527 } 528 } 529 530 return child.type(); 531 } 532 533 public Node exceptionCheck(ExceptionChecker ec) throws SemanticException { 534 if (ci == null) { 536 throw new InternalCompilerError(position(), 537 "Null constructor instance after type check."); 538 } 539 540 for (Iterator i = ci.throwTypes().iterator(); i.hasNext(); ) { 541 Type t = (Type) i.next(); 542 ec.throwsException(t, position()); 543 } 544 545 return super.exceptionCheck(ec); 546 } 547 548 549 public Precedence precedence() { 550 return Precedence.LITERAL; 551 } 552 553 public String toString() { 554 return (qualifier != null ? (qualifier.toString() + ".") : "") + 555 "new " + tn + "(...)" + (body != null ? " " + body : ""); 556 } 557 558 protected void printQualifier(CodeWriter w, PrettyPrinter tr) { 559 if (qualifier != null) { 560 print(qualifier, w, tr); 561 w.write("."); 562 } 563 } 564 565 protected void printArgs(CodeWriter w, PrettyPrinter tr) { 566 w.write("("); 567 w.begin(0); 568 569 for (Iterator i = arguments.iterator(); i.hasNext();) { 570 Expr e = (Expr) i.next(); 571 572 print(e, w, tr); 573 574 if (i.hasNext()) { 575 w.write(","); 576 w.allowBreak(0); 577 } 578 } 579 580 w.end(); 581 w.write(")"); 582 } 583 584 protected void printBody(CodeWriter w, PrettyPrinter tr) { 585 if (body != null) { 586 w.write(" {"); 587 print(body, w, tr); 588 w.write("}"); 589 } 590 } 591 592 public void prettyPrint(CodeWriter w, PrettyPrinter tr) { 593 printQualifier(w, tr); 594 w.write("new "); 595 print(tn, w, tr); 596 printArgs(w, tr); 597 printBody(w, tr); 598 } 599 600 public void translate(CodeWriter w, Translator tr) { 601 printQualifier(w, tr); 602 603 w.write("new "); 604 605 if (qualifier != null) { 606 ClassType ct = tn.type().toClass(); 607 608 if (! ct.isMember()) { 609 throw new InternalCompilerError("Cannot qualify a non-member " + 610 "class.", position()); 611 } 612 613 tr.setOuterClass(ct.outer()); 614 print(tn, w, tr); 615 tr.setOuterClass(null); 616 } 617 else { 618 print(tn, w, tr); 619 } 620 621 printArgs(w, tr); 622 printBody(w, tr); 623 } 624 625 public Term entry() { 626 if (qualifier != null) return qualifier.entry(); 627 Term afterArgs = this; 628 if (body() != null) { 629 afterArgs = body(); 630 } 631 return listEntry(arguments, afterArgs); 632 } 633 634 public List acceptCFG(CFGBuilder v, List succs) { 635 Term afterArgs = this; 636 if (body() != null) { 637 afterArgs = body(); 638 } 639 640 if (qualifier != null) { 641 v.visitCFG(qualifier, listEntry(arguments, afterArgs)); 642 } 643 644 v.visitCFGList(arguments, afterArgs); 645 646 if (body() != null) { 647 v.visitCFG(body(), this); 648 } 649 650 return succs; 651 } 652 653 public List throwTypes(TypeSystem ts) { 654 List l = new LinkedList(); 655 l.addAll(ci.throwTypes()); 656 l.addAll(ts.uncheckedExceptions()); 657 return l; 658 } 659 } 660 | Popular Tags |