    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    }