// // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // Print.cpp -- // // Author : Thierry Delisle // Created On : Tue May 21 16:20:15 2019 // Last Modified By : // Last Modified On : // Update Count : // #include "Print.hpp" #include "Decl.hpp" #include "Expr.hpp" #include "Stmt.hpp" #include "Type.hpp" #include "TypeSubstitution.hpp" namespace ast { template constexpr auto make_array(T&&... values) -> std::array { return std::array{ std::forward(values)... }; } class Printer : public Visitor { public: std::ostream & os; Indenter indent; Printer(std::ostream & os, Indenter indent) : os( os ), indent( indent ) {} private: template< typename C > void printAll( const C & c ) { for ( const auto & i : c ) { if ( i ) { os << indent; i->accept( *this ); // need an endl after each element because it's not // easy to know when each individual item should end os << std::endl; } // if } // for } static const char* Names[]; struct Names { static constexpr auto FuncSpecifiers = make_array( "inline", "_Noreturn", "fortran" ); static constexpr auto StorageClasses = make_array( "extern", "static", "auto", "register", "_Thread_local" ); static constexpr auto Qualifiers = make_array( "const", "restrict", "volatile", "lvalue", "mutex", "_Atomic" ); }; template void print(const storage_t & storage, const std::array & Names ) { if ( storage.any() ) { for ( size_t i = 0; i < Names.size(); i += 1 ) { if ( storage[i] ) { os << Names[i] << ' '; } } } } void print( const ast::Function::Specs & specs ) { print(specs, Names::FuncSpecifiers); } void print( const ast::Storage::Classes & storage ) { print(storage, Names::StorageClasses); } void print( const ast::CV::Qualifiers & qualifiers ) { print(qualifiers, Names::Qualifiers); } public: virtual const ast::DeclWithType * visit( const ast::ObjectDecl * node ) { if ( node->name != "" ) os << node->name << ": "; if ( node->linkage != Linkage::Cforall ) { os << Linkage::name( node->linkage ) << " "; } // if print( node->storage ); if ( node->type ) { node->type->accept( *this ); } else { os << " untyped entity "; } // if if ( node->init ) { os << " with initializer (" << ( node->init->maybeConstructed ? "maybe constructed" : "not constructed" ) << ")" << std::endl << indent+1; ++indent; node->init->accept( *this ); --indent; os << std::endl; } // if if ( ! node->attributes.empty() ) { os << std::endl << indent << "... with attributes:" << std::endl; ++indent; printAll( node->attributes ); --indent; } if ( node->bitfieldWidth ) { os << indent << " with bitfield width "; node->bitfieldWidth->accept( *this ); } // if return node; } virtual const ast::DeclWithType * visit( const ast::FunctionDecl * node ) { return node; } virtual const ast::Decl * visit( const ast::StructDecl * node ) { return node; } virtual const ast::Decl * visit( const ast::UnionDecl * node ) { return node; } virtual const ast::Decl * visit( const ast::EnumDecl * node ) { return node; } virtual const ast::Decl * visit( const ast::TraitDecl * node ) { return node; } virtual const ast::Decl * visit( const ast::TypeDecl * node ) { return node; } virtual const ast::Decl * visit( const ast::TypedefDecl * node ) { return node; } virtual const ast::AsmDecl * visit( const ast::AsmDecl * node ) { return node; } virtual const ast::StaticAssertDecl * visit( const ast::StaticAssertDecl * node ) { return node; } virtual const ast::CompoundStmt * visit( const ast::CompoundStmt * node ) { return node; } virtual const ast::Stmt * visit( const ast::ExprStmt * node ) { return node; } virtual const ast::Stmt * visit( const ast::AsmStmt * node ) { return node; } virtual const ast::Stmt * visit( const ast::DirectiveStmt * node ) { return node; } virtual const ast::Stmt * visit( const ast::IfStmt * node ) { return node; } virtual const ast::Stmt * visit( const ast::WhileStmt * node ) { return node; } virtual const ast::Stmt * visit( const ast::ForStmt * node ) { return node; } virtual const ast::Stmt * visit( const ast::SwitchStmt * node ) { return node; } virtual const ast::Stmt * visit( const ast::CaseStmt * node ) { return node; } virtual const ast::Stmt * visit( const ast::BranchStmt * node ) { return node; } virtual const ast::Stmt * visit( const ast::ReturnStmt * node ) { return node; } virtual const ast::Stmt * visit( const ast::ThrowStmt * node ) { return node; } virtual const ast::Stmt * visit( const ast::TryStmt * node ) { return node; } virtual const ast::Stmt * visit( const ast::CatchStmt * node ) { return node; } virtual const ast::Stmt * visit( const ast::FinallyStmt * node ) { return node; } virtual const ast::Stmt * visit( const ast::WaitForStmt * node ) { return node; } virtual const ast::Stmt * visit( const ast::WithStmt * node ) { return node; } virtual const ast::NullStmt * visit( const ast::NullStmt * node ) { return node; } virtual const ast::Stmt * visit( const ast::DeclStmt * node ) { return node; } virtual const ast::Stmt * visit( const ast::ImplicitCtorDtorStmt * node ) { return node; } virtual const ast::Expr * visit( const ast::ApplicationExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::UntypedExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::NameExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::AddressExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::LabelAddressExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::CastExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::KeywordCastExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::VirtualCastExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::UntypedMemberExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::MemberExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::VariableExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::ConstantExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::SizeofExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::AlignofExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::UntypedOffsetofExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::OffsetofExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::OffsetPackExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::LogicalExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::ConditionalExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::CommaExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::TypeExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::AsmExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::ImplicitCopyCtorExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::ConstructorExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::CompoundLiteralExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::RangeExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::UntypedTupleExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::TupleExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::TupleIndexExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::TupleAssignExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::StmtExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::UniqueExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::UntypedInitExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::InitExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::DeletedExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::DefaultArgExpr * node ) { return node; } virtual const ast::Expr * visit( const ast::GenericExpr * node ) { return node; } virtual const ast::Type * visit( const ast::VoidType * node ) { return node; } virtual const ast::Type * visit( const ast::BasicType * node ) { return node; } virtual const ast::Type * visit( const ast::PointerType * node ) { return node; } virtual const ast::Type * visit( const ast::ArrayType * node ) { return node; } virtual const ast::Type * visit( const ast::ReferenceType * node ) { return node; } virtual const ast::Type * visit( const ast::QualifiedType * node ) { return node; } virtual const ast::Type * visit( const ast::FunctionType * node ) { return node; } virtual const ast::Type * visit( const ast::StructInstType * node ) { return node; } virtual const ast::Type * visit( const ast::UnionInstType * node ) { return node; } virtual const ast::Type * visit( const ast::EnumInstType * node ) { return node; } virtual const ast::Type * visit( const ast::TraitInstType * node ) { return node; } virtual const ast::Type * visit( const ast::TypeInstType * node ) { return node; } virtual const ast::Type * visit( const ast::TupleType * node ) { return node; } virtual const ast::Type * visit( const ast::TypeofType * node ) { return node; } virtual const ast::Type * visit( const ast::VarArgsType * node ) { return node; } virtual const ast::Type * visit( const ast::ZeroType * node ) { return node; } virtual const ast::Type * visit( const ast::OneType * node ) { return node; } virtual const ast::Type * visit( const ast::GlobalScopeType * node ) { return node; } virtual const ast::Designation * visit( const ast::Designation * node ) { return node; } virtual const ast::Init * visit( const ast::SingleInit * node ) { return node; } virtual const ast::Init * visit( const ast::ListInit * node ) { return node; } virtual const ast::Init * visit( const ast::ConstructorInit * node ) { return node; } virtual const ast::Attribute * visit( const ast::Attribute * node ) { return node; } virtual const ast::TypeSubstitution * visit( const ast::TypeSubstitution * node ) { os << indent << "Types:" << std::endl; for ( const auto& i : *node ) { os << indent+1 << i.first << " -> "; indent += 2; i.second->accept( *this ); indent -= 2; os << std::endl; } os << indent << "Non-types:" << std::endl; for ( auto i = node->beginVar(); i != node->endVar(); ++i ) { os << indent+1 << i->first << " -> "; indent += 2; i->second->accept( *this ); indent -= 2; os << std::endl; } return node; } }; void print( std::ostream & os, const ast::Node * node, Indenter indent ) { Printer printer { os, indent }; node->accept(printer); } // Annoyingly these needed to be defined out of line to avoid undefined references. // The size here needs to be explicit but at least the compiler will produce an error // if the wrong size is specified constexpr std::array Printer::Names::FuncSpecifiers; constexpr std::array Printer::Names::StorageClasses; constexpr std::array Printer::Names::Qualifiers; }