/* * The JastAdd Extensible Java Compiler (http://jastadd.org) is covered * by the modified BSD License. You should have received a copy of the * modified BSD license with this compiler. * * Copyright (c) 2005-2008, Torbjorn Ekman * All rights reserved. */ module org.jastadd.java14frontend; import java.util.Iterator; public aspect PrettyPrint { // Helper for indentation static int ASTNode.indent = 0; public static String ASTNode.indent() { StringBuffer s = new StringBuffer(); for(int i = 0; i < indent; i++) { s.append(" "); } return s.toString(); } // Default output public String ASTNode.toString() { StringBuffer s = new StringBuffer(); toString(s); return s.toString().trim(); } public void ASTNode.toString(StringBuffer s) { throw new Error("Operation toString(StringBuffer s) not implemented for " + getClass().getName()); } public void Program.toString(StringBuffer s) { for(Iterator iter = compilationUnitIterator(); iter.hasNext(); ) { CompilationUnit cu = (CompilationUnit)iter.next(); if(cu.fromSource()) { cu.toString(s); } } } public void CompilationUnit.toString(StringBuffer s) { try { if(!getPackageDecl().equals("")) { s.append("package " + getPackageDecl() + ";\n"); } for(int i = 0; i < getNumImportDecl(); i++) { getImportDecl(i).toString(s); } for(int i = 0; i < getNumTypeDecl(); i++) { getTypeDecl(i).toString(s); s.append("\n"); } } catch (NullPointerException e) { System.out.print("Error in compilation unit hosting " + getTypeDecl(0).typeName()); throw e; } } public void SingleTypeImportDecl.toString(StringBuffer s) { s.append("import "); getAccess().toString(s); s.append(";\n"); } public void TypeImportOnDemandDecl.toString(StringBuffer s) { s.append("import "); getAccess().toString(s); s.append(".*;\n"); } public void ClassDecl.toString(StringBuffer s) { getModifiers().toString(s); s.append("class " + name()); if(hasSuperClassAccess()) { s.append(" extends "); getSuperClassAccess().toString(s); } if(getNumImplements() > 0) { s.append(" implements "); getImplements(0).toString(s); for(int i = 1; i < getNumImplements(); i++) { s.append(", "); getImplements(i).toString(s); } } s.append(" {\n"); indent++; for(int i=0; i < getNumBodyDecl(); i++) { getBodyDecl(i).toString(s); } indent--; s.append(indent() + "}\n"); } public void InterfaceDecl.toString(StringBuffer s) { getModifiers().toString(s); s.append("interface " + name()); if(getNumSuperInterfaceId() > 0) { s.append(" extends "); getSuperInterfaceId(0).toString(s); for(int i = 1; i < getNumSuperInterfaceId(); i++) { s.append(", "); getSuperInterfaceId(i).toString(s); } } s.append(" {\n"); indent++; for(int i=0; i < getNumBodyDecl(); i++) { getBodyDecl(i).toString(s); } indent--; s.append(indent() + "}\n"); } // Type body decl public void InstanceInitializer.toString(StringBuffer s) { if(getBlock().getNumStmt() > 0) { s.append(indent()); getBlock().toString(s); } } public void StaticInitializer.toString(StringBuffer s) { s.append(indent()); s.append("static "); getBlock().toString(s); } public void ConstructorDecl.toString(StringBuffer s) { s.append(indent()); getModifiers().toString(s); s.append(name() + "("); if(getNumParameter() > 0) { getParameter(0).toString(s); for(int i = 1; i < getNumParameter(); i++) { s.append(", "); getParameter(i).toString(s); } } s.append(")"); if(getNumException() > 0) { s.append(" throws "); getException(0).toString(s); for(int i = 1; i < getNumException(); i++) { s.append(", "); getException(i).toString(s); } } s.append(" {\n"); indent++; if(hasConstructorInvocation()) { s.append(indent()); getConstructorInvocation().toString(s); } for(int i = 0; i < getBlock().getNumStmt(); i++) { s.append(indent()); getBlock().getStmt(i).toString(s); } indent--; s.append(indent()); s.append("}\n"); } public void FieldDeclaration.toString(StringBuffer s) { s.append(indent()); getModifiers().toString(s); getTypeAccess().toString(s); s.append(" " + name()); if(hasInit()) { s.append(" = "); getInit().toString(s); } s.append(";\n"); } public void VariableDeclaration.toString(StringBuffer s) { getModifiers().toString(s); getTypeAccess().toString(s); s.append(" " + name()); if(hasInit()) { s.append(" = "); getInit().toString(s); } s.append(";\n"); } public void MethodDecl.toString(StringBuffer s) { s.append(indent()); getModifiers().toString(s); getTypeAccess().toString(s); s.append(" " + name() + "("); if(getNumParameter() > 0) { getParameter(0).toString(s); for(int i = 1; i < getNumParameter(); i++) { s.append(", "); getParameter(i).toString(s); } } s.append(")"); if(getNumException() > 0) { s.append(" throws "); getException(0).toString(s); for(int i = 1; i < getNumException(); i++) { s.append(", "); getException(i).toString(s); } } if(hasBlock()) { s.append(" "); getBlock().toString(s); } else { s.append(";\n"); } } public void MemberClassDecl.toString(StringBuffer s) { s.append(indent()); getClassDecl().toString(s); } public void MemberInterfaceDecl.toString(StringBuffer s) { s.append(indent()); getInterfaceDecl().toString(s); } public void EmptyType.toString(StringBuffer s) { s.append(indent()); s.append(";\n"); } public void ArrayInit.toString(StringBuffer s) { s.append("{ "); if(getNumInit() > 0) { getInit(0).toString(s); for(int i = 1; i < getNumInit(); i++) { s.append(", "); getInit(i).toString(s); } } s.append(" } "); } public void ParameterDeclaration.toString(StringBuffer s) { getModifiers().toString(s); getTypeAccess().toString(s); s.append(" " + name()); } // Assign Expression public void AssignExpr.toString(StringBuffer s) { getDest().toString(s); s.append(printOp()); getSource().toString(s); } syn String AssignExpr.printOp() = " = "; eq AssignSimpleExpr.printOp() = " = "; eq AssignMulExpr.printOp() = " *= "; eq AssignDivExpr.printOp() = " /= "; eq AssignModExpr.printOp() = " %= "; eq AssignPlusExpr.printOp() = " += "; eq AssignMinusExpr.printOp() = " -= "; eq AssignLShiftExpr.printOp() = " <<= "; eq AssignRShiftExpr.printOp() = " >>= "; eq AssignURShiftExpr.printOp() = " >>>= "; eq AssignAndExpr.printOp() = " &= "; eq AssignXorExpr.printOp() = " ^= "; eq AssignOrExpr.printOp() = " |= "; // Literals public void Literal.toString(StringBuffer s) { s.append(getLITERAL()); } public void StringLiteral.toString(StringBuffer s) { s.append("\"" + escape(getLITERAL()) + "\""); } public void CharacterLiteral.toString(StringBuffer s) { s.append("'" + escape(getLITERAL()) + "'"); } public void LongLiteral.toString(StringBuffer s) { s.append(getLITERAL()); s.append("L"); } public void FloatingPointLiteral.toString(StringBuffer s) { s.append(getLITERAL()); s.append("F"); } public void DoubleLiteral.toString(StringBuffer s) { s.append(getLITERAL()); s.append("D"); } static String Literal.escape(String s) { StringBuffer result = new StringBuffer(); for (int i=0; i < s.length(); i++) { switch(s.charAt(i)) { case '\b' : result.append("\\b"); break; case '\t' : result.append("\\t"); break; case '\n' : result.append("\\n"); break; case '\f' : result.append("\\f"); break; case '\r' : result.append("\\r"); break; case '\"' : result.append("\\\""); break; case '\'' : result.append("\\\'"); break; case '\\' : result.append("\\\\"); break; default: int value = (int)s.charAt(i); if(value < 0x20 || (value > 0x7e)) result.append(asEscape(value)); else result.append(s.charAt(i)); } } return result.toString(); } static String Literal.asEscape(int value) { StringBuffer s = new StringBuffer("\\u"); String hex = Integer.toHexString(value); for(int i = 0; i < 4-hex.length(); i++) s.append("0"); s.append(hex); return s.toString(); } public void ParExpr.toString(StringBuffer s) { s.append("("); getExpr().toString(s); s.append(")"); } public void ClassInstanceExpr.toString(StringBuffer s) { s.append("new "); getAccess().toString(s); s.append("("); if(getNumArg() > 0) { getArg(0).toString(s); for(int i = 1; i < getNumArg(); i++) { s.append(", "); getArg(i).toString(s); } } s.append(")"); if(hasTypeDecl()) { TypeDecl decl = getTypeDecl(); s.append(" {\n"); indent++; for(int i = 0; i < decl.getNumBodyDecl(); i++) { if(!(decl.getBodyDecl(i) instanceof ConstructorDecl)) decl.getBodyDecl(i).toString(s); } indent--; s.append(indent()); s.append("}"); } } public void ArrayCreationExpr.toString(StringBuffer s) { s.append("new "); getTypeAccess().toString(s); if(hasArrayInit()) { getArrayInit().toString(s); } } // Pre and post operations for unary expression public void Unary.toString(StringBuffer s) { s.append(printPreOp()); getOperand().toString(s); s.append(printPostOp()); } syn String Unary.printPostOp() = ""; eq PostIncExpr.printPostOp() = "++"; eq PostDecExpr.printPostOp() = "--"; syn String Unary.printPreOp() = ""; eq PreIncExpr.printPreOp() = "++"; eq PreDecExpr.printPreOp() = "--"; eq MinusExpr.printPreOp() = "-"; eq PlusExpr.printPreOp() = "+"; eq BitNotExpr.printPreOp() = "~"; eq LogNotExpr.printPreOp() = "!"; public void CastExpr.toString(StringBuffer s) { s.append("("); getTypeAccess().toString(s); s.append(")"); getExpr().toString(s); } // Binary Expr public void Binary.toString(StringBuffer s) { getLeftOperand().toString(s); s.append(printOp()); getRightOperand().toString(s); } syn String Binary.printOp(); eq MulExpr.printOp() = " * "; eq DivExpr.printOp() = " / "; eq ModExpr.printOp() = " % "; eq AddExpr.printOp() = " + "; eq SubExpr.printOp() = " - "; eq LShiftExpr.printOp() = " << "; eq RShiftExpr.printOp() = " >> "; eq URShiftExpr.printOp() = " >>> "; eq AndBitwiseExpr.printOp() = " & "; eq OrBitwiseExpr.printOp() = " | "; eq XorBitwiseExpr.printOp() = " ^ "; eq AndLogicalExpr.printOp() = " && "; eq OrLogicalExpr.printOp() = " || "; eq LTExpr.printOp() = " < "; eq GTExpr.printOp() = " > "; eq LEExpr.printOp() = " <= "; eq GEExpr.printOp() = " >= "; eq EQExpr.printOp() = " == "; eq NEExpr.printOp() = " != "; public void InstanceOfExpr.toString(StringBuffer s) { getExpr().toString(s); s.append(" instanceof "); getTypeAccess().toString(s); } public void ConditionalExpr.toString(StringBuffer s) { getCondition().toString(s); s.append(" ? "); getTrueExpr().toString(s); s.append(" : "); getFalseExpr().toString(s); } public void Modifiers.toString(StringBuffer s) { for(int i = 0; i < getNumModifier(); i++) { getModifier(i).toString(s); s.append(" "); } } public void Modifier.toString(StringBuffer s) { s.append(getID()); } public void AbstractDot.toString(StringBuffer s) { getLeft().toString(s); if(!nextAccess().isArrayAccess()) s.append("."); getRight().toString(s); } public void VarAccess.toString(StringBuffer s) { s.append(name()); } public void MethodAccess.toString(StringBuffer s) { s.append(name()); s.append("("); if(getNumArg() > 0) { getArg(0).toString(s); for(int i = 1; i < getNumArg(); i++) { s.append(", "); getArg(i).toString(s); } } s.append(")"); } public void ConstructorAccess.toString(StringBuffer s) { s.append(name()); s.append("("); if(getNumArg() > 0) { getArg(0).toString(s); for(int i = 1; i < getNumArg(); i++) { s.append(", "); getArg(i).toString(s); } } s.append(")"); } public void TypeAccess.toString(StringBuffer s) { if(decl().isReferenceType()) s.append(nameWithPackage()); else s.append(decl().name()); } public void ArrayTypeAccess.toString(StringBuffer s) { getAccess().toString(s); s.append("[]"); } public void ArrayTypeWithSizeAccess.toString(StringBuffer s) { getAccess().toString(s); s.append("["); getExpr().toString(s); s.append("]"); } public void ThisAccess.toString(StringBuffer s) { s.append("this"); } public void SuperAccess.toString(StringBuffer s) { s.append("super"); } public void PackageAccess.toString(StringBuffer s) { s.append(getPackage()); } public void ArrayAccess.toString(StringBuffer s) { s.append("["); getExpr().toString(s); s.append("]"); } public void ClassAccess.toString(StringBuffer s) { s.append("class"); } // Stmts public void Block.toString(StringBuffer s) { s.append("{\n"); indent++; for(int i = 0; i < getNumStmt(); i++) { s.append(indent()); getStmt(i).toString(s); } indent--; s.append(indent()); s.append("}\n"); } public void EmptyStmt.toString(StringBuffer s) { s.append(";\n"); } public void LabeledStmt.toString(StringBuffer s) { s.append(getLabel() + ":\n"); s.append(indent()); getStmt().toString(s); } public void ExprStmt.toString(StringBuffer s) { getExpr().toString(s); s.append(";\n"); } public void SwitchStmt.toString(StringBuffer s) { s.append("switch ("); getExpr().toString(s); s.append(")"); getBlock().toString(s); } public void ConstCase.toString(StringBuffer s) { s.append(indent()); s.append("case "); getValue().toString(s); s.append(":\n"); } public void DefaultCase.toString(StringBuffer s) { s.append(indent()); s.append("default:\n"); } public void IfStmt.toString(StringBuffer s) { s.append("if("); getCondition().toString(s); s.append(") "); getThen().toString(s); if(hasElse()) { s.append(indent()); s.append("else "); getElse().toString(s); } } public void WhileStmt.toString(StringBuffer s) { s.append("while("); getCondition().toString(s); s.append(") "); getStmt().toString(s); } public void DoStmt.toString(StringBuffer s) { s.append("do "); getStmt().toString(s); s.append("while("); getCondition().toString(s); s.append(");\n"); } public void ForStmt.toString(StringBuffer s) { s.append("for("); if(getNumInitStmt() > 0) { if(getInitStmt(0) instanceof VariableDeclaration) { int minDimension = Integer.MAX_VALUE; for(int i = 0; i < getNumInitStmt(); i++) { VariableDeclaration v = (VariableDeclaration)getInitStmt(i); minDimension = Math.min(minDimension, v.type().dimension()); } VariableDeclaration v = (VariableDeclaration)getInitStmt(0); v.getModifiers().toString(s); s.append(v.type().elementType().typeName()); for(int i = minDimension; i > 0; i--) s.append("[]"); for(int i = 0; i < getNumInitStmt(); i++) { if(i != 0) s.append(","); v = (VariableDeclaration)getInitStmt(i); s.append(" " + v.name()); for(int j = v.type().dimension() - minDimension; j > 0; j--) s.append("[]"); if(v.hasInit()) { s.append(" = "); v.getInit().toString(s); } } } else if(getInitStmt(0) instanceof ExprStmt) { ExprStmt stmt = (ExprStmt)getInitStmt(0); stmt.getExpr().toString(s); for(int i = 1; i < getNumInitStmt(); i++) { s.append(", "); stmt = (ExprStmt)getInitStmt(i); stmt.getExpr().toString(s); } } else { throw new Error("Unexpected initializer in for loop: " + getInitStmt(0)); } } s.append("; "); if(hasCondition()) { getCondition().toString(s); } s.append("; "); if(getNumUpdateStmt() > 0) { ExprStmt stmt = (ExprStmt)getUpdateStmt(0); stmt.getExpr().toString(s); for(int i = 1; i < getNumUpdateStmt(); i++) { s.append(", "); stmt = (ExprStmt)getUpdateStmt(i); stmt.getExpr().toString(s); } } s.append(") "); getStmt().toString(s); } public void BreakStmt.toString(StringBuffer s) { s.append("break "); if(hasLabel()) s.append(getLabel()); s.append(";\n"); } public void ContinueStmt.toString(StringBuffer s) { s.append("continue "); if(hasLabel()) s.append(getLabel()); s.append(";\n"); } public void ReturnStmt.toString(StringBuffer s) { s.append("return "); if(hasResult()) { getResult().toString(s); } s.append(";\n"); } public void ThrowStmt.toString(StringBuffer s) { s.append("throw "); getExpr().toString(s); s.append(";\n"); } public void SynchronizedStmt.toString(StringBuffer s) { s.append("synchronized("); getExpr().toString(s); s.append(") "); getBlock().toString(s); } public void TryStmt.toString(StringBuffer s) { s.append("try "); getBlock().toString(s); for(int i = 0; i < getNumCatchClause(); i++) { s.append(indent()); getCatchClause(i).toString(s); } if(hasFinally()) { s.append(indent()); s.append("finally "); getFinally().toString(s); } } public void CatchClause.toString(StringBuffer s) { s.append("catch ("); getParameter().toString(s); s.append(") "); getBlock().toString(s); } public void AssertStmt.toString(StringBuffer s) { s.append("assert "); getfirst().toString(s); if(hasExpr()) { s.append(" : "); getExpr().toString(s); } s.append(";\n"); } public void LocalClassDeclStmt.toString(StringBuffer s) { getClassDecl().toString(s); } // dump the AST to standard output public String ASTNode.dumpTree() { StringBuffer s = new StringBuffer(); dumpTree(s, 0); return s.toString(); } public void ASTNode.dumpTree(StringBuffer s, int j) { for(int i = 0; i < j; i++) { s.append(" "); } s.append(dumpString() + "\n"); for(int i = 0; i < getNumChild(); i++) getChild(i).dumpTree(s, j + 1); } public String ASTNode.dumpTreeNoRewrite() { StringBuffer s = new StringBuffer(); dumpTreeNoRewrite(s, 0); return s.toString(); } //NEIL: Changed to allow access across modules public void ASTNode.dumpTreeNoRewrite(StringBuffer s, int indent) { for(int i = 0; i < indent; i++) s.append(" "); s.append(dumpString()); s.append("\n"); for(int i = 0; i < getNumChildNoTransform(); i++) { getChildNoTransform(i).dumpTreeNoRewrite(s, indent+1); } } //NEIL: Changed to allow access across modules public syn String ASTNode.dumpString() = getClass().getName(); eq CompilationUnit.dumpString() = getClass().getName() + " [" + getPackageDecl() + "]"; eq VarAccess.dumpString() = getClass().getName() + " [" + getID() + "]"; eq MethodAccess.dumpString() = getClass().getName() + " [" + getID() + "]"; eq TypeAccess.dumpString() = getClass().getName() + " [" + getPackage() + ", " + getID() + "]"; eq ArrayTypeAccess.dumpString() = getClass().getName(); eq PackageAccess.dumpString() = getClass().getName() + " [" + getPackage() + "]"; eq ParseName.dumpString() = getClass().getName() + " [" + getID() + "]"; eq PackageOrTypeAccess.dumpString() = getClass().getName() + " [" + getID() + "]"; eq AmbiguousAccess.dumpString() = getClass().getName() + " [" + getID() + "]"; eq TypeDecl.dumpString() = getClass().getName() + " [" + getID() + "]"; eq FieldDeclaration.dumpString() = getClass().getName() + " [" + getID() + "]"; eq VariableDeclaration.dumpString() = getClass().getName() + " [" + getID() + "]"; eq ParameterDeclaration.dumpString() = getClass().getName() + " [" + getID() + "]"; eq MethodDecl.dumpString() = getClass().getName() + " [" + getID() + "]"; eq Modifier.dumpString() = getClass().getName() + " [" + getID() + "]"; eq Literal.dumpString() = getClass().getName() + " [" + getLITERAL() + "]"; eq BoundTypeAccess.dumpString() = getClass().getName() + " [" + getTypeDecl().fullName() + "]"; public String Program.dumpTree() { StringBuffer s = new StringBuffer(); for(Iterator iter = compilationUnitIterator(); iter.hasNext(); ) { CompilationUnit cu = (CompilationUnit)iter.next(); if(cu.fromSource()) { s.append(cu.dumpTree()); } } return s.toString(); } }