// // 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. // // Indexer.cc -- // // Author : Richard C. Bilson // Created On : Sun May 17 21:37:33 2015 // Last Modified By : Peter A. Buhr // Last Modified On : Sun May 17 21:38:44 2015 // Update Count : 2 // #include "SynTree/Declaration.h" #include "SynTree/Type.h" #include "SynTree/Expression.h" #include "SynTree/Initializer.h" #include "SynTree/Statement.h" #include "Indexer.h" #include #include "utility.h" #define debugPrint(x) if ( doDebug ) { std::cout << x; } namespace SymTab { Indexer::Indexer( bool useDebug ) : doDebug( useDebug ) {} Indexer::~Indexer() {} void Indexer::visit( ObjectDecl *objectDecl ) { maybeAccept( objectDecl->get_type(), *this ); maybeAccept( objectDecl->get_init(), *this ); maybeAccept( objectDecl->get_bitfieldWidth(), *this ); if ( objectDecl->get_name() != "" ) { debugPrint( "Adding object " << objectDecl->get_name() << std::endl ); idTable.addDecl( objectDecl ); } // if } void Indexer::visit( FunctionDecl *functionDecl ) { if ( functionDecl->get_name() == "" ) return; debugPrint( "Adding function " << functionDecl->get_name() << std::endl ); idTable.addDecl( functionDecl ); enterScope(); maybeAccept( functionDecl->get_functionType(), *this ); acceptAll( functionDecl->get_oldDecls(), *this ); maybeAccept( functionDecl->get_statements(), *this ); leaveScope(); } /******** * A NOTE ON THE ORDER OF TRAVERSAL * * Types and typedefs have their base types visited before they are added to the type table. * This is ok, since there is no such thing as a recursive type or typedef. * typedef struct { T *x; } T; // never allowed * * for structs/unions, it is possible to have recursion, so the decl should be added as if it's * incomplete to begin, the members are traversed, and then the complete type should be added * (assuming the type is completed by this particular declaration). * struct T { struct T *x; }; // allowed * * It's important to add the complete type to the symbol table *after* the members/base has been * traversed, since that traversal may modify the definition of the type and these modifications * should be visible when the symbol table is queried later in this pass. * * TODO: figure out whether recursive contexts are sensible/possible/reasonable. */ void Indexer::visit( TypeDecl *typeDecl ) { // see A NOTE ON THE ORDER OF TRAVERSAL, above // note that assertions come after the type is added to the symtab, since they aren't part // of the type proper and may depend on the type itself enterScope(); acceptAll( typeDecl->get_parameters(), *this ); maybeAccept( typeDecl->get_base(), *this ); leaveScope(); debugPrint( "Adding type " << typeDecl->get_name() << std::endl ); typeTable.add( typeDecl ); acceptAll( typeDecl->get_assertions(), *this ); } void Indexer::visit( TypedefDecl *typeDecl ) { enterScope(); acceptAll( typeDecl->get_parameters(), *this ); maybeAccept( typeDecl->get_base(), *this ); leaveScope(); debugPrint( "Adding typedef " << typeDecl->get_name() << std::endl ); typeTable.add( typeDecl ); } void Indexer::visit( StructDecl *aggregateDecl ) { // make up a forward declaration and add it before processing the members StructDecl fwdDecl( aggregateDecl->get_name() ); cloneAll( aggregateDecl->get_parameters(), fwdDecl.get_parameters() ); debugPrint( "Adding fwd decl for struct " << fwdDecl.get_name() << std::endl ); structTable.add( &fwdDecl ); enterScope(); acceptAll( aggregateDecl->get_parameters(), *this ); acceptAll( aggregateDecl->get_members(), *this ); leaveScope(); debugPrint( "Adding struct " << aggregateDecl->get_name() << std::endl ); // this addition replaces the forward declaration structTable.add( aggregateDecl ); } void Indexer::visit( UnionDecl *aggregateDecl ) { // make up a forward declaration and add it before processing the members UnionDecl fwdDecl( aggregateDecl->get_name() ); cloneAll( aggregateDecl->get_parameters(), fwdDecl.get_parameters() ); debugPrint( "Adding fwd decl for union " << fwdDecl.get_name() << std::endl ); unionTable.add( &fwdDecl ); enterScope(); acceptAll( aggregateDecl->get_parameters(), *this ); acceptAll( aggregateDecl->get_members(), *this ); leaveScope(); debugPrint( "Adding union " << aggregateDecl->get_name() << std::endl ); unionTable.add( aggregateDecl ); } void Indexer::visit( EnumDecl *aggregateDecl ) { debugPrint( "Adding enum " << aggregateDecl->get_name() << std::endl ); enumTable.add( aggregateDecl ); // unlike structs, contexts, and unions, enums inject their members into the global scope acceptAll( aggregateDecl->get_members(), *this ); } void Indexer::visit( ContextDecl *aggregateDecl ) { enterScope(); acceptAll( aggregateDecl->get_parameters(), *this ); acceptAll( aggregateDecl->get_members(), *this ); leaveScope(); debugPrint( "Adding context " << aggregateDecl->get_name() << std::endl ); contextTable.add( aggregateDecl ); } void Indexer::visit( CompoundStmt *compoundStmt ) { enterScope(); acceptAll( compoundStmt->get_kids(), *this ); leaveScope(); } void Indexer::visit( ContextInstType *contextInst ) { acceptAll( contextInst->get_parameters(), *this ); acceptAll( contextInst->get_members(), *this ); } void Indexer::visit( StructInstType *structInst ) { if ( ! structTable.lookup( structInst->get_name() ) ) { debugPrint( "Adding struct " << structInst->get_name() << " from implicit forward declaration" << std::endl ); structTable.add( structInst->get_name() ); } enterScope(); acceptAll( structInst->get_parameters(), *this ); leaveScope(); } void Indexer::visit( UnionInstType *unionInst ) { if ( ! unionTable.lookup( unionInst->get_name() ) ) { debugPrint( "Adding union " << unionInst->get_name() << " from implicit forward declaration" << std::endl ); unionTable.add( unionInst->get_name() ); } enterScope(); acceptAll( unionInst->get_parameters(), *this ); leaveScope(); } void Indexer::visit( ForStmt *forStmt ) { // for statements introduce a level of scope enterScope(); Visitor::visit( forStmt ); leaveScope(); } void Indexer::lookupId( const std::string &id, std::list< DeclarationWithType* > &list ) const { idTable.lookupId( id, list ); } DeclarationWithType* Indexer::lookupId( const std::string &id) const { return idTable.lookupId(id); } NamedTypeDecl *Indexer::lookupType( const std::string &id ) const { return typeTable.lookup( id ); } StructDecl *Indexer::lookupStruct( const std::string &id ) const { return structTable.lookup( id ); } EnumDecl *Indexer::lookupEnum( const std::string &id ) const { return enumTable.lookup( id ); } UnionDecl *Indexer::lookupUnion( const std::string &id ) const { return unionTable.lookup( id ); } ContextDecl * Indexer::lookupContext( const std::string &id ) const { return contextTable.lookup( id ); } void Indexer::enterScope() { if ( doDebug ) { std::cout << "--- Entering scope" << std::endl; } idTable.enterScope(); typeTable.enterScope(); structTable.enterScope(); enumTable.enterScope(); unionTable.enterScope(); contextTable.enterScope(); } void Indexer::leaveScope() { using std::cout; using std::endl; if ( doDebug ) { cout << "--- Leaving scope containing" << endl; idTable.dump( cout ); typeTable.dump( cout ); structTable.dump( cout ); enumTable.dump( cout ); unionTable.dump( cout ); contextTable.dump( cout ); } idTable.leaveScope(); typeTable.leaveScope(); structTable.leaveScope(); enumTable.leaveScope(); unionTable.leaveScope(); contextTable.leaveScope(); } void Indexer::print( std::ostream &os, int indent ) const { using std::cerr; using std::endl; cerr << "===idTable===" << endl; idTable.dump( os ); cerr << "===typeTable===" << endl; typeTable.dump( os ); cerr << "===structTable===" << endl; structTable.dump( os ); cerr << "===enumTable===" << endl; enumTable.dump( os ); cerr << "===unionTable===" << endl; unionTable.dump( os ); cerr << "===contextTable===" << endl; contextTable.dump( os ); #if 0 idTable.dump( os ); typeTable.dump( os ); structTable.dump( os ); enumTable.dump( os ); unionTable.dump( os ); contextTable.dump( os ); #endif } } // namespace SymTab // Local Variables: // // tab-width: 4 // // mode: c++ // // compile-command: "make install" // // End: //