001 /* Copyright 2000, 2001, Compaq Computer Corporation */ 002 003 package javafe.ast; 004 005 import java.io.OutputStream; 006 import java.io.ByteArrayOutputStream; 007 import java.io.IOException; 008 import javafe.util.Assert; 009 import javafe.util.Location; 010 011 public class StandardPrettyPrint extends PrettyPrint { 012 013 public StandardPrettyPrint() { } 014 015 //@ requires self != null; 016 public StandardPrettyPrint(PrettyPrint self) { super(self); } 017 018 public void print(OutputStream o, CompilationUnit cu) { 019 if (cu == null) { 020 writeln(o, "<null CompilationUnit>"); 021 return; 022 } 023 if (cu.lexicalPragmas != null) { 024 for (int i = 0; i < cu.lexicalPragmas.size(); i++) 025 self.print(o, cu.lexicalPragmas.elementAt(i)); 026 writeln(o); 027 } 028 if (cu.pkgName != null) { 029 write(o, "package "); self.print(o, cu.pkgName); writeln(o, ";"); 030 writeln(o); 031 } 032 if (cu.imports.size() > 0) { 033 for(int j=0; j<cu.imports.size(); j++) { 034 ImportDecl i = cu.imports.elementAt(j); 035 write(o, "import "); 036 if (i instanceof SingleTypeImportDecl) 037 self.print(o, ((SingleTypeImportDecl)i).typeName); 038 else { 039 self.print(o, ((OnDemandImportDecl)i).pkgName); //@ nowarn Cast; 040 write(o, ".*"); 041 } 042 writeln(o, ";"); 043 } 044 writeln(o); 045 } 046 for(int j=0; j<cu.elems.size(); j++) { 047 self.print(o, 0, cu.elems.elementAt(j)); 048 writeln(o); 049 } 050 for (int j=0; j<cu.otherPragmas.size(); ++j) { 051 TypeDeclElemPragma tde = (TypeDeclElemPragma)cu.otherPragmas.elementAt(j); 052 self.print(o, 0, tde); 053 } 054 } 055 056 public void printnoln(OutputStream o, int ind, TypeDecl d) { 057 if (d == null) { 058 write(o, "<null TypeDecl>"); 059 return; 060 } 061 062 if (d.specOnly) { 063 writeln(o); 064 spaces(o, ind); 065 writeln(o, "/* Only specification information is available for " 066 + "this type */"); 067 writeln(o); 068 spaces(o, ind); 069 } 070 071 if (d.pmodifiers != null) 072 for (int i = 0; i < d.pmodifiers.size(); i++) { 073 self.print(o, ind, d.pmodifiers.elementAt(i)); 074 writeln(o); 075 spaces(o, ind); 076 } 077 String mod = Modifiers.toString(d.modifiers); 078 if (!mod.equals("")) { 079 writeln(o, mod); 080 spaces(o, ind); 081 } 082 083 Identifier id; 084 085 switch (d.getTag()) { 086 087 case TagConstants.CLASSDECL: 088 { 089 ClassDecl cd = (ClassDecl)d; 090 writeln(o, "class "+(id=cd.id)); 091 if (cd.superClass != null) { 092 if (!toString(cd.superClass).equals("java.lang.Object") 093 || PrettyPrint.displayInferred) { 094 spaces(o, ind); 095 write(o, "extends "); 096 self.print(o, cd.superClass); 097 writeln(o); 098 } 099 } 100 if (cd.superInterfaces.size() != 0) { 101 spaces(o, ind); 102 write(o, "implements "); 103 self.print(o, cd.superInterfaces); 104 writeln(o); 105 } 106 break; 107 } 108 109 case TagConstants.INTERFACEDECL: 110 { 111 InterfaceDecl cd = (InterfaceDecl)d; 112 writeln(o, "interface "+(id=cd.id)); 113 if (cd.superInterfaces.size() != 0) { 114 spaces(o, ind); 115 write(o, "extends "); 116 self.print(o, cd.superInterfaces); 117 writeln(o,""); 118 } 119 break; 120 } 121 122 default: 123 spaces(o, ind); 124 writeln(o, unknownTag(d)); 125 id = Identifier.intern("?"); 126 } 127 128 spaces(o, ind); 129 writeln(o, "{"); 130 for (int i = 0; i < d.elems.size(); i++) { 131 TypeDeclElem elem = d.elems.elementAt(i); 132 //@ assume elem.hasParent ; // "invariant" 133 spaces(o, ind+INDENT); 134 self.print(o, ind+INDENT, elem, id, true); 135 if (i != d.elems.size()-1) writeln(o); 136 } 137 spaces(o, ind); 138 write(o, "}"); 139 } 140 141 public void print(OutputStream o, int ind, Stmt s) { 142 if (s == null) { 143 writeln(o, "<null Stmt>"); 144 return; 145 } 146 147 switch (s.getTag()) { 148 149 case TagConstants.RETURNSTMT: 150 { 151 ReturnStmt r = (ReturnStmt)s; 152 if (r.expr == null) 153 write(o, "return;"); 154 else { 155 write(o, "return "); 156 self.print(o, ind, r.expr); 157 write(o, ';'); 158 } 159 return; 160 } 161 162 case TagConstants.THROWSTMT: 163 { 164 ThrowStmt t = (ThrowStmt)s; 165 write(o, "throw "); self.print(o, ind, t.expr); write(o, ';'); 166 return; 167 } 168 169 case TagConstants.ASSERTSTMT: { 170 AssertStmt a = (AssertStmt)s; 171 write(o, "assert "); self.print(o, ind, a.pred); //write(o, ")"); 172 if (a.label != null) { 173 write(o, " : "); 174 self.print(o, ind, a.label); 175 } 176 write(o, ";"); 177 return; 178 } 179 180 case TagConstants.SWITCHSTMT: 181 { 182 SwitchStmt c = (SwitchStmt)s; 183 write(o, "switch ("); self.print(o, ind, c.expr); write(o, ") "); 184 // Fall through 185 } 186 187 case TagConstants.BLOCKSTMT: 188 { 189 GenericBlockStmt b = (GenericBlockStmt)s; 190 int nextInd = ind + INDENT; 191 writeln(o, "{"); 192 boolean lastWasLabel = false; 193 for(int i = 0; i < b.stmts.size(); i++) { 194 Stmt sub = b.stmts.elementAt(i); 195 if (sub.getTag() == TagConstants.SWITCHLABEL) { 196 SwitchLabel x = (SwitchLabel)sub; 197 if (x.expr == null && sub.getStartLoc() == b.locCloseBrace) { 198 // this is an implicit "default: break;" statement 199 Assert.notFalse(i == b.stmts.size() - 2); //@ nowarn Pre; 200 // don't print this statement or the next, which should be 201 // a "break" 202 Assert.notFalse(b.stmts.elementAt(i+1).getTag() //@ nowarn Pre; 203 == TagConstants.BREAKSTMT); 204 if (!PrettyPrint.displayInferred) 205 break; 206 } 207 if (i != 0 && ! lastWasLabel) writeln(o); 208 if (x.expr == null) { spaces(o, ind); writeln(o, "default:"); } 209 else { 210 spaces(o, ind); 211 write(o, "case "); 212 self.print(o, ind, x.expr); 213 writeln(o, ":"); 214 } 215 lastWasLabel = true; 216 } else { 217 spaces(o, nextInd); 218 self.print(o, nextInd, sub); 219 writeln(o); 220 lastWasLabel = false; 221 } 222 } 223 spaces(o, ind); 224 write(o, '}'); 225 return; 226 } 227 228 case TagConstants.WHILESTMT: 229 { 230 WhileStmt w = (WhileStmt)s; 231 write(o, "while ("); self.print(o, ind, w.expr); write(o, ") "); 232 self.print(o, ind, w.stmt); 233 return; 234 } 235 236 case TagConstants.DOSTMT: 237 { 238 DoStmt d = (DoStmt)s; 239 write(o, "do "); 240 self.print(o, ind, d.stmt); 241 write(o, " while ("); self.print(o, ind, d.expr); write(o, ");"); 242 return; 243 } 244 245 case TagConstants.IFSTMT: 246 { 247 IfStmt i = (IfStmt)s; 248 write(o, "if ("); self.print(o, ind, i.expr); write(o, ") "); 249 self.print(o, ind, i.thn); 250 if (! (i.els.getTag() == TagConstants.SKIPSTMT)) { 251 write(o, '\n'); 252 spaces(o, ind); write(o, "else "); self.print(o, ind, i.els); 253 } 254 return; 255 } 256 257 case TagConstants.BREAKSTMT: 258 { 259 BreakStmt b = (BreakStmt)s; 260 if (b.label == null) write(o, "break;"); 261 else { 262 write(o, "break "); 263 write(o, b.label.toString()); 264 write(o, ';'); 265 } 266 return; 267 } 268 269 case TagConstants.CONTINUESTMT: 270 { 271 ContinueStmt c = (ContinueStmt)s; 272 if (c.label == null) write(o, "continue;"); 273 else { 274 write(o, "continue "); 275 write(o, c.label.toString()); 276 write(o, ';'); 277 } 278 return; 279 } 280 281 case TagConstants.SYNCHRONIZESTMT: 282 { 283 SynchronizeStmt x = (SynchronizeStmt)s; 284 if (x.stmt.getTag() == TagConstants.BLOCKSTMT) { 285 write(o, "synchronized ("); 286 self.print(o, ind, x.expr); 287 write(o, ") "); 288 self.print(o, ind, x.stmt); 289 } else { 290 write(o, "synchronized ("); 291 self.print(o, ind, x.expr); 292 write(o, ") {\n"); 293 spaces(o, ind+INDENT); 294 self.print(o, ind+INDENT, x.stmt); 295 spaces(o, ind); 296 write(o, '}'); 297 } 298 return; 299 } 300 301 case TagConstants.EVALSTMT: 302 { 303 EvalStmt x = (EvalStmt)s; 304 self.print(o, ind, x.expr); write(o, ';'); 305 return; 306 } 307 308 case TagConstants.LABELSTMT: 309 { 310 LabelStmt x = (LabelStmt)s; 311 write(o, x.label.toString()); 312 write(o, ": "); 313 self.print(o, ind, x.stmt); 314 return; 315 } 316 317 case TagConstants.SKIPSTMT: 318 write(o, ';'); 319 return; 320 321 case TagConstants.TRYFINALLYSTMT: 322 { 323 TryFinallyStmt x = (TryFinallyStmt)s; 324 if (x.tryClause.getTag() == TagConstants.TRYCATCHSTMT) 325 self.print(o, ind, x.tryClause); 326 else if (x.tryClause instanceof BlockStmt) { 327 write(o, "try "); 328 self.print(o, ind, x.tryClause); 329 } else { 330 write(o, "try {\b"); 331 spaces(o, ind); 332 self.print(o, ind+INDENT, x.tryClause); 333 spaces(o, ind); 334 write(o, '}'); 335 } 336 337 if (x.finallyClause.getTag() == TagConstants.BLOCKSTMT) { 338 write(o, " finally "); 339 self.print(o, ind, x.finallyClause); 340 } else { 341 write(o, " finally {\n"); 342 spaces(o, ind); 343 self.print(o, ind+INDENT, x.finallyClause); 344 spaces(o, ind); 345 write(o, '}'); 346 } 347 return; 348 } 349 350 case TagConstants.TRYCATCHSTMT: 351 { 352 TryCatchStmt x = (TryCatchStmt)s; 353 if (x.tryClause.getTag() == TagConstants.BLOCKSTMT) { 354 write(o, "try "); 355 self.print(o, ind, x.tryClause); 356 } else { 357 write(o, "try {\n"); 358 spaces(o, ind+INDENT); 359 self.print(o, ind+INDENT, x.tryClause); 360 spaces(o, ind); 361 write(o, '}'); 362 } 363 364 for(int i = 0; i < x.catchClauses.size(); i++) { 365 CatchClause c = x.catchClauses.elementAt(i); 366 write(o, " catch ("); self.print(o, c.arg); write(o, ") "); 367 self.print(o, ind, c.body); 368 } 369 return; 370 } 371 372 case TagConstants.CLASSDECLSTMT: 373 { 374 ClassDecl x = ((ClassDeclStmt)s).decl; 375 self.printnoln(o, ind, x); 376 return; 377 } 378 379 case TagConstants.VARDECLSTMT: 380 { 381 LocalVarDecl x = ((VarDeclStmt)s).decl; 382 self.print(o, ind, x, true); 383 return; 384 } 385 386 case TagConstants.FORSTMT: 387 { 388 ForStmt x = (ForStmt)s; 389 write(o, "for ("); 390 391 if (x.forInit.size() > 0) 392 if (x.forInit.elementAt(0).getTag() == TagConstants.VARDECLSTMT) { 393 self.print(o, ((VarDeclStmt)x.forInit.elementAt(0))//@nowarn Cast; 394 .decl.type); 395 write(o, ' '); 396 for(int i = 0; i < x.forInit.size(); i++) { 397 VarDeclStmt d = (VarDeclStmt)x.forInit.elementAt(i); //@nowarn Cast; 398 write(o, d.decl.id.toString()); 399 if (d.decl.init != null) { 400 write(o, '='); 401 self.print(o, ind, d.decl.init); 402 } 403 if (i+1 < x.forInit.size()) write(o, ", "); 404 } 405 } else 406 for(int i = 0; i < x.forInit.size(); i++) { 407 EvalStmt e = (EvalStmt) x.forInit.elementAt(i); //@nowarn Cast; 408 self.print(o, ind, e.expr); 409 if (i+1 < x.forInit.size()) write(o, ", "); 410 } 411 write(o, "; "); 412 self.print(o, ind, x.test); 413 write(o, "; "); 414 for(int i = 0; i < x.forUpdate.size(); i++) { 415 self.print(o, ind, x.forUpdate.elementAt(i)); 416 if (i+1 < x.forUpdate.size()) write(o, ", "); 417 } 418 write(o, ") "); 419 self.print(o, ind, x.body); 420 return; 421 } 422 423 case TagConstants.CONSTRUCTORINVOCATION: { 424 ConstructorInvocation x = (ConstructorInvocation)s; 425 if (x.enclosingInstance != null) { 426 if (!(x.enclosingInstance instanceof ThisExpr) || 427 !(((ThisExpr)x.enclosingInstance).inferred) || 428 PrettyPrint.displayInferred) { 429 self.print(o, ind, x.enclosingInstance); 430 write(o, "."); 431 } 432 } 433 write(o, (x.superCall ? "super" : "this")); 434 self.print(o, ind, x.args); 435 write(o, ';'); 436 return; 437 } 438 439 case TagConstants.SWITCHLABEL: { 440 /* 441 * This case never happens unless a client directly calls us on 442 * a SwitchLabel; normally block and switch statements handle 443 * switch labels directly for better formating (multiple 444 * cases/line). 445 */ 446 SwitchLabel x = (SwitchLabel)s; 447 448 if (x.expr == null) 449 writeln(o, "default:"); 450 else { 451 write(o, "case "); 452 self.print(o, ind, x.expr); 453 writeln(o, ":"); 454 } 455 return; 456 } 457 458 default: 459 if (s instanceof StmtPragma) 460 self.print(o, ind, (StmtPragma)s); 461 else write(o, unknownTag(s)); 462 return; 463 } 464 } 465 466 public void print(OutputStream o, int ind, TypeDeclElem d, 467 Identifier classId, boolean showBody) { 468 if (d == null) { 469 writeln(o, "<null TypeDeclElem>"); 470 return; 471 } 472 switch( d.getTag() ) { 473 474 case TagConstants.FIELDDECL: 475 self.print(o, ind, (FieldDecl)d, showBody); writeln(o); 476 break; 477 478 case TagConstants.INITBLOCK: 479 { 480 if (showBody) { 481 InitBlock si = (InitBlock)d; 482 write(o, Modifiers.toString(si.modifiers)); 483 if (si.pmodifiers != null) 484 for (int i = 0; i < si.pmodifiers.size(); i++) { 485 write(o, ' '); 486 self.print(o, ind, si.pmodifiers.elementAt(i)); 487 } 488 self.print(o, ind, si.block); 489 writeln(o); 490 } 491 break; 492 } 493 494 case TagConstants.METHODDECL: 495 { 496 MethodDecl md = (MethodDecl)d; 497 498 if (md.id.toString().equals("<clinit>")) { 499 break; 500 } 501 502 write(o, Modifiers.toString(md.modifiers)); 503 self.print(o, md.returnType); 504 write(o, ' '); 505 write(o, md.id.toString()); 506 self.print(o, ind, md.args); 507 if (md.raises.size() != 0) 508 { write(o, " throws "); self.print(o, md.raises); } 509 if (md.pmodifiers != null) { 510 for (int i = 0; i < md.pmodifiers.size(); i++) { 511 writeln(o); 512 spaces(o, ind+1); 513 self.print(o, ind, md.pmodifiers.elementAt(i)); 514 } 515 write(o, ' '); 516 } 517 displayBody(o,ind, md.body, showBody, 518 d.getParent().specOnly, 519 "method"); 520 break; 521 } 522 523 case TagConstants.CONSTRUCTORDECL: 524 { 525 ConstructorDecl md = (ConstructorDecl)d; 526 527 // Don't print default constructors: 528 if (md.implicit && !PrettyPrint.displayInferred) { 529 // need to at least do a <newline> here! 530 writeln(o, "// <default constructor>"); 531 break; 532 } 533 534 write(o, Modifiers.toString(md.modifiers)); 535 write(o, classId.toString()); 536 self.print(o, ind, md.args); 537 if (md.raises.size() != 0) 538 { write(o, " throws "); self.print(o, md.raises); } 539 if (md.pmodifiers != null) { 540 for (int i = 0; i < md.pmodifiers.size(); i++) { 541 writeln(o); 542 spaces(o, ind+1); 543 self.print(o, ind, md.pmodifiers.elementAt(i)); 544 } 545 write(o, ' '); 546 } 547 548 displayBody(o, ind, md.body, showBody, 549 d.getParent().specOnly, 550 "constructor"); 551 break; 552 } 553 554 case TagConstants.CLASSDECL: 555 case TagConstants.INTERFACEDECL: 556 { 557 self.print(o, ind, (TypeDecl)d); 558 break; 559 } 560 561 default: 562 if (d instanceof TypeDeclElemPragma) 563 self.print(o, ind, (TypeDeclElemPragma)d); 564 else writeln(o, unknownTagMsg(d.getTag())); 565 break; 566 } 567 } 568 569 570 //@ requires o != null; 571 void displayBody(OutputStream o, int ind, BlockStmt body, 572 boolean showBody, boolean specOnly, String kind) { 573 if (!showBody || body==null) { 574 writeln(o, ";"); 575 return; 576 } 577 578 writeln(o); 579 spaces(o, ind); 580 581 if (specOnly) { 582 writeln(o,"{"); 583 spaces(o, ind); 584 writeln(o, " /* " + kind + " body unavailable */"); 585 spaces(o, ind); 586 writeln(o,"}"); 587 } else { 588 self.print(o, ind, body); 589 writeln(o); 590 } 591 } 592 593 594 public void print(OutputStream o, TypeNameVec tns) { 595 if (tns == null) write(o, "<null TypeNameVec>"); 596 else 597 for( int i=0; i<tns.size(); i++ ) { 598 if (i != 0) write(o, ", "); 599 self.print(o, tns.elementAt(i)); 600 } 601 } 602 603 public void print(OutputStream o, int ind, FormalParaDeclVec fps) { 604 if (fps == null) write(o, "<null FormalParaDeclVec>"); 605 else { 606 write(o, '('); 607 for (int i=0; i<fps.size(); i++) { 608 if (i != 0) write(o, ", "); 609 610 FormalParaDecl d = fps.elementAt(i); 611 write(o, Modifiers.toString(d.modifiers)); 612 self.print(o, d); 613 if (d.pmodifiers != null) 614 for (int j = 0; j < d.pmodifiers.size(); j++) { 615 write(o, ' '); 616 self.print(o, ind, d.pmodifiers.elementAt(j)); 617 } 618 } 619 write(o, ')'); 620 } 621 } 622 623 public void print(OutputStream o, int ind, ExprVec es) { 624 if (es == null) write(o, "<null ExprVec>"); 625 else { 626 write(o, '('); 627 for (int i = 0; i < es.size(); i++) { 628 if (i != 0) write(o, ", "); 629 self.print(o, ind, es.elementAt(i)); 630 } 631 write(o, ')'); 632 } 633 } 634 635 public void print(OutputStream o, GenericVarDecl d) { 636 if (d == null) write(o, "<null GenericVarDecl>"); 637 else { 638 self.print(o, d.type); 639 write(o, ' '); 640 write(o, d.id.toString()); 641 } 642 } 643 644 public void print(OutputStream o, int ind, LocalVarDecl d, 645 boolean showBody) { 646 if (d == null) write(o, "<null VarDecl>"); 647 else { 648 write(o, Modifiers.toString(d.modifiers)); 649 self.print(o, d.type); 650 write(o, ' '); 651 write(o, d.id.toString()); 652 if (showBody && d.init != null) 653 { write(o, " = "); self.print(o, ind, d.init); } 654 if (d.pmodifiers != null) 655 for (int i = 0; i < d.pmodifiers.size(); i++) { 656 write(o, ' '); 657 self.print(o, ind, d.pmodifiers.elementAt(i)); 658 } 659 write(o, ';'); 660 } 661 } 662 663 public void print(OutputStream o, int ind, FieldDecl d, boolean showBody) { 664 if (d == null) write(o, "<null VarDecl>"); 665 else { 666 write(o, Modifiers.toString(d.modifiers)); 667 self.print(o, d.type); 668 write(o, ' '); 669 write(o, d.id.toString()); 670 if (showBody && d.init != null) 671 { write(o, " = "); self.print(o, ind, d.init); } 672 if (d.pmodifiers != null) 673 for (int i = 0; i < d.pmodifiers.size(); i++) { 674 write(o, ' '); 675 self.print(o, ind, d.pmodifiers.elementAt(i)); 676 } 677 write(o, ';'); 678 } 679 } 680 681 public void print(OutputStream o, Type t) { 682 if (t == null) { write(o, "<null Type>"); return; } 683 switch (t.getTag()) { 684 case TagConstants.BOOLEANTYPE: write(o, "boolean"); break; 685 case TagConstants.BYTETYPE: write(o, "byte"); break; 686 case TagConstants.ERRORTYPE: write(o, "error"); break; 687 case TagConstants.SHORTTYPE: write(o, "short"); break; 688 case TagConstants.INTTYPE: write(o, "int"); break; 689 case TagConstants.LONGTYPE: write(o, "long"); break; 690 case TagConstants.CHARTYPE: write(o, "char"); break; 691 case TagConstants.FLOATTYPE: write(o, "float"); break; 692 case TagConstants.DOUBLETYPE: write(o, "double"); break; 693 case TagConstants.VOIDTYPE: write(o, "void"); break; 694 case TagConstants.NULLTYPE: write(o, "null"); break; 695 case TagConstants.TYPENAME: 696 self.print(o, ((TypeName)t).name); break; 697 case TagConstants.ARRAYTYPE: 698 self.print(o, ((ArrayType)t).elemType); write(o, "["); 699 write(o,"]"); 700 break; 701 default: 702 write(o, t.toString() ); 703 break; 704 } 705 print(o, 2, t.tmodifiers); 706 } 707 708 public void print(OutputStream o, Name n) { 709 if (n == null) write(o, "<null Name>"); 710 else write(o, n.printName()); 711 } 712 713 static public void println(VarInit e) { 714 inst.print(System.out,0,e); 715 System.out.println(""); 716 } 717 718 public void print(OutputStream o, int ind, VarInit e) { 719 if (e == null) { 720 write(o, "<null expression>"); 721 return; 722 } 723 724 int eTag = e.getTag(); 725 switch (eTag) { 726 727 case TagConstants.ARRAYINIT: 728 { 729 VarInitVec v = ((ArrayInit)e).elems; 730 write(o, "{ "); 731 for(int i = 0; i < v.size(); i++) { 732 if (i != 0 ) write(o, ", "); 733 self.print(o, ind, v.elementAt(i)); 734 } 735 write(o, " }"); 736 return; 737 } 738 739 case TagConstants.THISEXPR: { 740 ThisExpr t = (ThisExpr)e; 741 if (t.classPrefix != null) { 742 self.print(o, t.classPrefix); 743 write(o, "."); 744 } 745 write(o, "this"); 746 return; 747 } 748 749 // Literals 750 case TagConstants.BOOLEANLIT: 751 case TagConstants.STRINGLIT: 752 case TagConstants.CHARLIT: 753 case TagConstants.DOUBLELIT: 754 case TagConstants.FLOATLIT: 755 case TagConstants.INTLIT: 756 case TagConstants.LONGLIT: 757 write(o, toCanonicalString(eTag, ((LiteralExpr)e).value)); 758 return; 759 760 case TagConstants.NULLLIT: 761 write(o, "null"); 762 return; 763 764 case TagConstants.ARRAYREFEXPR: 765 { 766 ArrayRefExpr r = (ArrayRefExpr)e; 767 self.print(o, ind, r.array); 768 write(o, '['); self.print(o, ind, r.index); write(o, ']'); 769 return; 770 } 771 772 case TagConstants.NEWINSTANCEEXPR: 773 { 774 NewInstanceExpr ne = (NewInstanceExpr)e; 775 if (ne.enclosingInstance != null) { 776 if (!(ne.enclosingInstance instanceof ThisExpr) || 777 !(((ThisExpr)ne.enclosingInstance).inferred) || 778 PrettyPrint.displayInferred) { 779 self.print(o, ind, ne.enclosingInstance); 780 write(o, "."); 781 } 782 } 783 write(o, "new "); self.print(o, ne.type); self.print(o, ind, ne.args); 784 if (ne.anonDecl != null) { 785 writeln(o, " {"); 786 for (int i = 0; i < ne.anonDecl.elems.size(); i++) { 787 TypeDeclElem elem = ne.anonDecl.elems.elementAt(i); 788 //@ assume elem.hasParent; // "invariant" 789 spaces(o, ind+INDENT); 790 self.print(o, ind+INDENT, elem, ne.anonDecl.id, true); 791 if (i != ne.anonDecl.elems.size()-1) writeln(o); 792 } 793 spaces(o, ind); 794 write(o, "}"); 795 } 796 return; 797 } 798 799 case TagConstants.NEWARRAYEXPR: 800 { 801 NewArrayExpr na = (NewArrayExpr)e; 802 Type basetype = na.type; 803 int cnt; 804 805 for (cnt = 0; basetype.getTag() == TagConstants.ARRAYTYPE; cnt++) { 806 basetype = ((ArrayType)basetype).elemType; 807 } 808 write(o, "new "); self.print(o, basetype); 809 for(int i=0; i<na.dims.size(); i++) { 810 write(o, '['); 811 if (na.init == null) { 812 self.print(o, ind, na.dims.elementAt(i)); 813 } 814 write(o, ']'); 815 } 816 for ( ; 0 < cnt; cnt--) write(o, "[]"); 817 if (na.init != null) self.print(o, ind, na.init); 818 return; 819 } 820 821 case TagConstants.CONDEXPR: 822 { 823 CondExpr ce = (CondExpr)e; 824 self.print(o, ind, ce.test); write(o, " ? "); 825 self.print(o, ind, ce.thn); write(o, " : "); 826 self.print(o, ind, ce.els); 827 return; 828 } 829 830 case TagConstants.INSTANCEOFEXPR: 831 { 832 InstanceOfExpr ie = (InstanceOfExpr)e; 833 self.print(o, ind, ie.expr); 834 write(o, " instanceof "); 835 self.print(o, ie.type); 836 return; 837 } 838 839 case TagConstants.CASTEXPR: 840 { 841 CastExpr ce = (CastExpr)e; 842 write(o, '('); self.print(o, ce.type); write(o, ')'); 843 self.print(o, ind, ce.expr); 844 return; 845 } 846 847 case TagConstants.CLASSLITERAL: 848 { 849 ClassLiteral cl = (ClassLiteral)e; 850 self.print(o, cl.type); write(o, ".class"); 851 return; 852 } 853 854 // Binary expressions 855 case TagConstants.OR: case TagConstants.AND: 856 case TagConstants.BITOR: case TagConstants.BITXOR: 857 case TagConstants.BITAND: case TagConstants.NE: 858 case TagConstants.EQ: case TagConstants.GE: 859 case TagConstants.GT: case TagConstants.LE: 860 case TagConstants.LT: case TagConstants.LSHIFT: 861 case TagConstants.RSHIFT: case TagConstants.URSHIFT: 862 case TagConstants.ADD: case TagConstants.SUB: 863 case TagConstants.DIV: case TagConstants.MOD: 864 case TagConstants.STAR: 865 case TagConstants.ASSIGN: case TagConstants.ASGMUL: 866 case TagConstants.ASGDIV: case TagConstants.ASGREM: 867 case TagConstants.ASGADD: case TagConstants.ASGSUB: 868 case TagConstants.ASGLSHIFT: case TagConstants.ASGRSHIFT: 869 case TagConstants.ASGURSHIFT: case TagConstants.ASGBITAND: 870 case TagConstants.ASGBITOR: case TagConstants.ASGBITXOR: 871 { 872 BinaryExpr be = (BinaryExpr)e; 873 self.print(o, ind, be.left); write(o, ' '); 874 write(o, OperatorTags.toString(be.op)); write(o, ' '); 875 self.print(o, ind, be.right); 876 return; 877 } 878 879 // Unary expressions 880 case TagConstants.UNARYSUB: case TagConstants.UNARYADD: 881 case TagConstants.NOT: case TagConstants.BITNOT: 882 case TagConstants.INC: case TagConstants.DEC: 883 case TagConstants.POSTFIXINC: case TagConstants.POSTFIXDEC: 884 { 885 UnaryExpr ue = (UnaryExpr)e; 886 if (ue.op == TagConstants.POSTFIXINC) 887 { self.print(o, ind, ue.expr); write(o, "++"); } 888 else if (ue.op == TagConstants.POSTFIXDEC) 889 { self.print(o, ind, ue.expr); write(o, "--"); } 890 else { 891 write(o, OperatorTags.toString(ue.op)); 892 write(o, " "); self.print(o, ind, ue.expr); 893 } 894 return; 895 } 896 897 case TagConstants.PARENEXPR: 898 { 899 ParenExpr pe = (ParenExpr)e; 900 write(o, '('); self.print(o, ind, pe.expr); write(o, ')'); 901 return; 902 } 903 904 case TagConstants.AMBIGUOUSVARIABLEACCESS: 905 self.print(o, ((AmbiguousVariableAccess)e).name); 906 return; 907 908 case TagConstants.VARIABLEACCESS: 909 { 910 VariableAccess lva = (VariableAccess)e; 911 write(o, lva.decl.id.toString()); 912 return; 913 } 914 915 case TagConstants.FIELDACCESS: 916 { 917 FieldAccess a = (FieldAccess)e; 918 self.print(o, ind, a.od); write(o, a.id.toString()); 919 return; 920 } 921 922 case TagConstants.AMBIGUOUSMETHODINVOCATION: 923 { 924 AmbiguousMethodInvocation ie = (AmbiguousMethodInvocation)e; 925 self.print(o, ie.name); self.print(o, ind, ie.args); 926 return; 927 } 928 929 case TagConstants.METHODINVOCATION: 930 { 931 MethodInvocation ie = (MethodInvocation)e; 932 self.print(o, ind, ie.od); 933 write(o, ie.id.toString()); 934 self.print(o, ind, ie.args); 935 return; 936 } 937 938 default: 939 write(o, unknownTag(e)); 940 return; 941 } 942 } 943 944 public void print(OutputStream o, int ind, ObjectDesignator od) { 945 if (od == null) { write(o, "<null object designator>"); return; } 946 switch (od.getTag()) { 947 case TagConstants.EXPROBJECTDESIGNATOR: 948 { 949 ExprObjectDesignator a = (ExprObjectDesignator)od; 950 if (a.expr.getTag() != TagConstants.THISEXPR 951 || !((ThisExpr)a.expr).inferred 952 || PrettyPrint.displayInferred) 953 { self.print(o, ind, a.expr); write(o, '.'); } 954 return; 955 } 956 957 case TagConstants.TYPEOBJECTDESIGNATOR: 958 { 959 TypeObjectDesignator a = (TypeObjectDesignator)od; 960 if (a.type.getTag() == TagConstants.TYPENAME 961 || PrettyPrint.displayInferred) 962 { self.print(o, a.type); write(o, '.'); } 963 return; 964 } 965 966 case TagConstants.SUPEROBJECTDESIGNATOR: 967 write(o, "super."); 968 return; 969 970 default: 971 write(o, unknownTag(od)); 972 break; 973 } 974 } 975 976 //// toString methods 977 978 /** 979 * Requires that <code>tag</code> is one of constants on the left of this 980 * table: 981 * <center><code><table> 982 * <tr> <td> TagConstants.BOOLEANLIT </td> <td> Boolean </td> </tr> 983 * <tr> <td> TagConstants.CHARLIT </td> <td> Integer </td> </tr> 984 * <tr> <td> TagConstants.DOUBLELIT </td> <td> Double </td> </tr> 985 * <tr> <td> TagConstants.FLOATLIT </td> <td> Float </td> </tr> 986 * <tr> <td> TagConstants.INTLIT </td> <td> Integer </td> </tr> 987 * <tr> <td> TagConstants.LONGLIT </td> <td> Long </td> </tr> 988 * <tr> <td> TagConstants.STRINGLIT </td> <td> String </td> </tr> 989 * </center></code></table> 990 * 991 * and that <code>val</code> is an instance of the corresponding type 992 * on the right. 993 * @return a canonical text representation for literal values. 994 */ 995 996 /*@ requires ((tag==TagConstants.BOOLEANLIT) || 997 @ (tag==TagConstants.INTLIT) || 998 @ (tag==TagConstants.LONGLIT) || 999 @ (tag==TagConstants.FLOATLIT) || 1000 @ (tag==TagConstants.DOUBLELIT) || 1001 @ (tag==TagConstants.STRINGLIT) || 1002 @ (tag==TagConstants.CHARLIT)); 1003 @*/ 1004 /*@ requires (((tag==TagConstants.BOOLEANLIT) ==> (val instanceof Boolean)) && 1005 @ ((tag==TagConstants.INTLIT) ==> (val instanceof Integer)) && 1006 @ ((tag==TagConstants.LONGLIT) ==> (val instanceof Long)) && 1007 @ ((tag==TagConstants.FLOATLIT) ==> (val instanceof Float)) && 1008 @ ((tag==TagConstants.DOUBLELIT) ==> (val instanceof Double)) && 1009 @ ((tag==TagConstants.STRINGLIT) ==> (val instanceof String)) && 1010 @ ((tag==TagConstants.CHARLIT) ==> (val instanceof Integer))); 1011 @*/ 1012 //@ ensures \result != null; 1013 public static String toCanonicalString(int tag, Object val) { 1014 if (tag == TagConstants.BOOLEANLIT) return val.toString(); 1015 1016 if (tag == TagConstants.DOUBLELIT) { 1017 String s = val.toString(); 1018 if (s.equals("Infinity")) return "1.0 / 0.0"; 1019 if (s.equals("-Infinity")) return "-1.0 / 0.0"; 1020 if (s.equals("NaN")) return "0.0d / 0.0"; 1021 return val.toString() + "D"; 1022 } 1023 1024 if (tag == TagConstants.FLOATLIT) { 1025 String s = val.toString(); 1026 if (s.equals("Infinity")) return "1.0f / 0.0f"; 1027 if (s.equals("-Infinity")) return "-1.0f / 0.0f"; 1028 if (s.equals("NaN")) return "0.0f / 0.0f"; 1029 return val.toString() + "F"; 1030 } 1031 1032 if (tag == TagConstants.INTLIT) { 1033 int v = ((Integer) val).intValue(); 1034 if (v == Integer.MIN_VALUE) return "0x80000000"; 1035 else if (v < 0) return "0x" + Integer.toHexString(v); 1036 else return Integer.toString(v); 1037 } 1038 1039 if (tag == TagConstants.LONGLIT) { 1040 long v = ((Long) val).longValue(); 1041 if (v == Long.MIN_VALUE) return "0x8000000000000000L"; 1042 else if (v < 0) return "0x" + Long.toHexString(v) + "L"; 1043 else return Long.toString(v) + "L"; 1044 } 1045 1046 if (tag == TagConstants.CHARLIT || tag == TagConstants.STRINGLIT) { 1047 char quote; 1048 if (tag == TagConstants.CHARLIT) { 1049 quote = '\''; 1050 val = new Character((char)((Integer)val).intValue()); 1051 } else quote = '\"'; 1052 String s = val.toString(); 1053 StringBuffer result = new StringBuffer(s.length()+2); 1054 result.append(quote); 1055 for(int i = 0, len = s.length(); i < len; i++) { 1056 char c = s.charAt(i); 1057 switch (c) { 1058 case '\b': result.append("\\b"); break; 1059 case '\t': result.append("\\t"); break; 1060 case '\n': result.append("\\n"); break; 1061 case '\f': result.append("\\f"); break; 1062 case '\r': result.append("\\r"); break; 1063 case '\"': result.append("\\\""); break; 1064 case '\'': result.append("\\'"); break; 1065 case '\\': result.append("\\\\"); break; 1066 default: 1067 if (32 <= c && c < 128) result.append(c); 1068 else { 1069 result.append("\\u"); 1070 for(int j=12; j>=0; j-=4) 1071 result.append(Character.forDigit((c>>j)&0xf, 16)); 1072 } 1073 } 1074 } 1075 result.append(quote); 1076 return result.toString(); 1077 } 1078 1079 Assert.precondition(false); 1080 return null; // Dummy 1081 } 1082 1083 public void print(OutputStream o, LexicalPragma lp) { 1084 write(o, "// Lexical pragma at " + lp.getStartLoc() + " "); 1085 writeln(o, lp.toString()); 1086 } 1087 1088 public void print(OutputStream o, int ind, TypeDeclElemPragma tp) { 1089 spaces(o, ind); 1090 write(o, "// TypeDeclElemPragma pragma at " + tp.getStartLoc() + " "); 1091 write(o, tp.toString()); 1092 } 1093 1094 public void print(OutputStream o, int ind, ModifierPragma mp) { 1095 write(o, "// ModifierPragma pragma at " + mp.getStartLoc() + " "); 1096 write(o, mp.toString()); 1097 } 1098 1099 public void print(OutputStream o, int ind, StmtPragma sp) { 1100 spaces(o, ind); 1101 write(o, "// StmtPragma pragma at " + sp.getStartLoc() + " "); 1102 write(o, sp.toString()); 1103 } 1104 1105 1106 public void print(OutputStream o, int ind, TypeModifierPragma tp) { 1107 spaces(o, ind); 1108 write(o, "// TypeModifierPragma pragma at " + tp.getStartLoc() + " "); 1109 write(o, tp.toString()); 1110 } 1111 1112 //@ requires o != null; 1113 public void print(OutputStream o, int ind, TypeModifierPragmaVec t) { 1114 if (t != null) { 1115 for (int i = 0; i < t.size(); i++) { 1116 write(o, ' '); 1117 self.print(o, ind, t.elementAt(i)); 1118 } 1119 } 1120 } 1121 1122 /** 1123 * Generate text to describe a ASTNote with an unknown tag 1124 */ 1125 //@ requires n != null; 1126 //@ ensures \result != null; 1127 public String unknownTag(ASTNode n) { 1128 return unknownTagMsg(n.getTag()); 1129 } 1130 1131 /** 1132 * Generate text to describe a given unknown tag 1133 */ 1134 //@ ensures \result != null; 1135 public String unknownTagMsg(int tag) { 1136 return "UnknownTag<" + tag + ":" 1137 + PrettyPrint.inst.toString(tag) + ">"; 1138 } 1139 }