00001 //===-- ast/DiagPrint.cpp ------------------------------------- -*- C++ -*-===// 00002 // 00003 // This file is distributed under the MIT license. See LICENSE.txt for details. 00004 // 00005 // Copyright (C) 2009, Stephen Wilson 00006 // 00007 //===----------------------------------------------------------------------===// 00008 00009 #include "comma/ast/DeclVisitor.h" 00010 #include "comma/ast/Expr.h" 00011 #include "comma/ast/ExprVisitor.h" 00012 #include "comma/ast/DiagPrint.h" 00013 #include "comma/ast/TypeVisitor.h" 00014 00015 using namespace comma; 00016 using llvm::dyn_cast; 00017 using llvm::cast; 00018 using llvm::isa; 00019 00020 namespace { 00021 00022 //===----------------------------------------------------------------------===// 00023 // PrettyPrinter. 00024 // 00028 class PrettyPrinter : private TypeVisitor, 00029 private DeclVisitor { 00030 00031 public: 00032 PrettyPrinter(llvm::raw_ostream &stream) : stream(stream) { } 00033 00034 void print(Type *type) { visitType(type); } 00035 void print(Decl *decl) { visitDecl(decl); } 00036 00037 private: 00038 llvm::raw_ostream &stream; 00039 00040 // Type printers. 00041 void visitDomainType(DomainType *node); 00042 void visitSubroutineType(SubroutineType *node); 00043 void visitEnumerationType(EnumerationType *node); 00044 void visitIntegerType(IntegerType *node); 00045 void visitArrayType(ArrayType *node); 00046 void visitRecordType(RecordType *node); 00047 00048 // Decl printers. Currently only a few are supported. 00049 void visitFunctionDecl(FunctionDecl *node); 00050 void visitProcedureDecl(ProcedureDecl *node); 00051 void visitDomainTypeDecl(DomainTypeDecl *node); 00052 00053 // Helper methods. 00054 void printParameterProfile(SubroutineDecl *node); 00055 void printQualifiedName(const char *name, DeclRegion *region); 00056 }; 00057 00058 } // end anonymous namespace 00059 00060 //===----------------------------------------------------------------------===// 00061 // PrettyPrinter methods. 00062 00063 void PrettyPrinter::visitDomainType(DomainType *node) 00064 { 00065 visitDomainTypeDecl(node->getDomainTypeDecl()); 00066 } 00067 00068 void PrettyPrinter::visitSubroutineType(SubroutineType *node) 00069 { 00070 if (isa<FunctionType>(node)) 00071 stream << "function"; 00072 else 00073 stream << "procedure"; 00074 00075 if (node->getArity() != 0) { 00076 stream << '('; 00077 SubroutineType::arg_type_iterator I = node->begin(); 00078 visitType(*I); 00079 while (++I != node->end()) { 00080 stream << ", "; 00081 visitType(*I); 00082 } 00083 stream << ')'; 00084 } 00085 00086 if (isa<FunctionType>(node)) { 00087 stream << " return "; 00088 visitType(cast<FunctionType>(node)->getReturnType()); 00089 } 00090 } 00091 00092 void PrettyPrinter::visitEnumerationType(EnumerationType *node) 00093 { 00094 stream << node->getIdInfo()->getString(); 00095 } 00096 00097 void PrettyPrinter::visitIntegerType(IntegerType *node) 00098 { 00099 stream << node->getIdInfo()->getString(); 00100 } 00101 00102 void PrettyPrinter::visitArrayType(ArrayType *node) 00103 { 00104 stream << node->getIdInfo()->getString(); 00105 } 00106 00107 void PrettyPrinter::visitRecordType(RecordType *node) 00108 { 00109 stream << node->getIdInfo()->getString(); 00110 } 00111 00112 void PrettyPrinter::printParameterProfile(SubroutineDecl *node) 00113 { 00114 unsigned arity = node->getArity(); 00115 00116 if (arity == 0) 00117 return; 00118 00119 stream << " ("; 00120 for (unsigned i = 0; i < arity; ++i) { 00121 IdentifierInfo *key = node->getParamKeyword(i); 00122 stream << key->getString() << ": "; 00123 00124 switch (node->getParamMode(i)) { 00125 case PM::MODE_DEFAULT: 00126 case PM::MODE_IN: 00127 stream << "in "; 00128 break; 00129 case PM::MODE_OUT: 00130 stream << "out "; 00131 break; 00132 case PM::MODE_IN_OUT: 00133 stream << "in out "; 00134 break; 00135 } 00136 00137 visitType(node->getParamType(i)); 00138 00139 if (i + 1 != arity) 00140 stream << "; "; 00141 } 00142 stream << ')'; 00143 } 00144 00145 void PrettyPrinter::printQualifiedName(const char *name, DeclRegion *region) 00146 { 00147 typedef llvm::SmallVector<Ast*, 4> ParentSet; 00148 ParentSet parents; 00149 00150 while (region) { 00151 // Bump past AddDecl's and add the containing PercentDecl. 00152 Ast *ast = region->asAst(); 00153 if (isa<AddDecl>(ast)) { 00154 region = region->getParent(); 00155 parents.push_back(region->asAst()); 00156 } 00157 else 00158 parents.push_back(ast); 00159 region = region->getParent(); 00160 } 00161 00162 ParentSet::reverse_iterator I = parents.rbegin(); 00163 ParentSet::reverse_iterator E = parents.rend(); 00164 for (; I != E; ++I) { 00165 if (DomainTypeDecl *decl = dyn_cast<DomainTypeDecl>(*I)) 00166 visitDomainTypeDecl(decl); 00167 else if (Decl *decl = dyn_cast<Decl>(*I)) 00168 stream << decl->getString(); 00169 stream << '.'; 00170 } 00171 00172 stream << name; 00173 } 00174 00175 void PrettyPrinter::visitFunctionDecl(FunctionDecl *node) 00176 { 00177 stream << "function "; 00178 printQualifiedName(node->getString(), node->getDeclRegion()); 00179 printParameterProfile(node); 00180 stream << " return "; 00181 visitType(node->getReturnType()); 00182 } 00183 00184 void PrettyPrinter::visitProcedureDecl(ProcedureDecl *node) 00185 { 00186 stream << "procedure "; 00187 printQualifiedName(node->getString(), node->getDeclRegion()); 00188 printParameterProfile(node); 00189 } 00190 00191 void PrettyPrinter::visitDomainTypeDecl(DomainTypeDecl *node) 00192 { 00193 if (isa<PercentDecl>(node)) 00194 stream << '%'; 00195 else if (DomainInstanceDecl *decl = dyn_cast<DomainInstanceDecl>(node)) { 00196 stream << decl->getString(); 00197 00198 if (decl->isParameterized()) { 00199 stream << '('; 00200 DomainInstanceDecl::arg_iterator I = decl->beginArguments(); 00201 visitDomainTypeDecl(*I); 00202 while (++I != decl->endArguments()) { 00203 stream << ", "; 00204 visitDomainTypeDecl(*I); 00205 } 00206 stream << ')'; 00207 } 00208 } 00209 else if (AbstractDomainDecl *decl = dyn_cast<AbstractDomainDecl>(node)) 00210 stream << decl->getString(); 00211 } 00212 00213 00214 //===----------------------------------------------------------------------===// 00215 // Public API. 00216 00217 void diag::PrintType::print(llvm::raw_ostream &stream) const 00218 { 00219 PrettyPrinter(stream).print(type); 00220 } 00221 00222 void diag::PrintDecl::print(llvm::raw_ostream &stream) const 00223 { 00224 PrettyPrinter(stream).print(decl); 00225 }