00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 #include "comma/ast/AstResource.h"
00011 #include "comma/ast/AstRewriter.h"
00012 #include "comma/ast/Decl.h"
00013 #include "comma/ast/DeclRegion.h"
00014 #include "comma/ast/DeclRewriter.h"
00015 #include "comma/ast/Stmt.h"
00016 #include "comma/ast/Type.h"
00017 
00018 #include "llvm/Support/Casting.h"
00019 
00020 #include <algorithm>
00021 #include <cstring>
00022 #include <cassert>
00023 
00024 using namespace comma;
00025 using llvm::dyn_cast;
00026 using llvm::cast;
00027 using llvm::isa;
00028 
00029 void DeclRegion::addDecl(Decl *decl) {
00030     declarations.push_back(decl);
00031     notifyObserversOfAddition(decl);
00032 }
00033 
00034 void DeclRegion::addDeclarationUsingRewrites(DeclRewriter &rewrites,
00035                                              Decl *decl)
00036 {
00037     addDecl(rewrites.rewriteDecl(decl));
00038 }
00039 
00040 void
00041 DeclRegion::addDeclarationsUsingRewrites(DeclRewriter &rewrites,
00042                                          const DeclRegion *region)
00043 {
00044     ConstDeclIter E = region->endDecls();
00045     for (ConstDeclIter I = region->beginDecls(); I != E; ++I)
00046         addDecl(rewrites.rewriteDecl(*I));
00047 }
00048 
00049 Decl *DeclRegion::findDecl(IdentifierInfo *name, Type *type)
00050 {
00051     DeclIter endIter = endDecls();
00052     for (DeclIter iter = beginDecls(); iter != endIter; ++iter) {
00053         Decl *decl = *iter;
00054         if (decl->getIdInfo() == name) {
00055             Type *candidate = 0;
00056             if (TypeDecl *TD = dyn_cast<TypeDecl>(decl))
00057                 candidate = TD->getType();
00058             else if (SubroutineDecl *SD = dyn_cast<SubroutineDecl>(decl))
00059                 candidate = SD->getType();
00060             else if (ValueDecl *VD = dyn_cast<ValueDecl>(decl))
00061                 candidate = VD->getType();
00062 
00063             if (candidate && type == candidate)
00064                 return decl;
00065         }
00066     }
00067     return 0;
00068 }
00069 
00070 DeclRegion::PredRange
00071 DeclRegion::findDecls(IdentifierInfo *name) const
00072 {
00073     struct Pred : public PredIter::Predicate {
00074         Pred(IdentifierInfo *name) : name(name) { }
00075         bool operator()(const Decl *decl) {
00076             return decl->getIdInfo() == name;
00077         }
00078         IdentifierInfo *name;
00079     };
00080     ConstDeclIter begin = beginDecls();
00081     ConstDeclIter end   = endDecls();
00082     Pred         *pred  = new Pred(name);
00083     return PredRange(PredIter(pred, begin, end), PredIter(end));
00084 }
00085 
00086 bool DeclRegion::removeDecl(Decl *decl)
00087 {
00088     DeclIter result = std::find(beginDecls(), endDecls(), decl);
00089     if (result != endDecls()) {
00090         declarations.erase(result);
00091         return true;
00092     }
00093     return false;
00094 }
00095 
00096 bool DeclRegion::containsDecl(const Decl *decl) const
00097 {
00098     ConstDeclIter I = beginDecls();
00099     ConstDeclIter E = endDecls();
00100     ConstDeclIter P = std::find(I, E, decl);
00101     return P != E;
00102 }
00103 
00104 bool DeclRegion::collectFunctionDecls(
00105     IdentifierInfo *name, llvm::SmallVectorImpl<SubroutineDecl*> &dst)
00106 {
00107     PredRange range = findDecls(name);
00108     size_t size = dst.size();
00109 
00110     for (PredIter iter = range.first; iter != range.second; ++iter) {
00111         if (FunctionDecl *decl = dyn_cast<FunctionDecl>(*iter))
00112             dst.push_back(decl);
00113     }
00114     return size != dst.size();
00115 }
00116 
00117 bool DeclRegion::collectProcedureDecls(
00118     IdentifierInfo *name, llvm::SmallVectorImpl<SubroutineDecl*> &dst)
00119 {
00120     PredRange range = findDecls(name);
00121     size_t size = dst.size();
00122 
00123     for (PredIter iter = range.first; iter != range.second; ++iter) {
00124         if (ProcedureDecl *decl = dyn_cast<ProcedureDecl>(*iter))
00125             dst.push_back(decl);
00126     }
00127     return size != dst.size();
00128 }
00129 
00130 const Ast *DeclRegion::asAst() const
00131 {
00132     switch (regionKind) {
00133     default:
00134         assert(false && "Unknown delcarative region kind!");
00135         return 0;
00136     case Ast::AST_PercentDecl:
00137         return static_cast<const PercentDecl*>(this);
00138     case Ast::AST_FunctionDecl:
00139         return static_cast<const FunctionDecl*>(this);
00140     case Ast::AST_ProcedureDecl:
00141         return static_cast<const ProcedureDecl*>(this);
00142     case Ast::AST_AbstractDomainDecl:
00143         return static_cast<const AbstractDomainDecl*>(this);
00144     case Ast::AST_DomainInstanceDecl:
00145         return static_cast<const DomainInstanceDecl*>(this);
00146     case Ast::AST_AddDecl:
00147         return static_cast<const AddDecl*>(this);
00148     case Ast::AST_EnumerationDecl:
00149         return static_cast<const EnumerationDecl*>(this);
00150     case Ast::AST_BlockStmt:
00151         return static_cast<const BlockStmt*>(this);
00152     case Ast::AST_IntegerDecl:
00153         return static_cast<const IntegerDecl*>(this);
00154     case Ast::AST_RecordDecl:
00155         return static_cast<const RecordDecl*>(this);
00156     case Ast::AST_ArrayDecl:
00157         return static_cast<const ArrayDecl*>(this);
00158     case Ast::AST_AccessDecl:
00159         return static_cast<const AccessDecl*>(this);
00160     }
00161 }
00162 
00163 Ast *DeclRegion::asAst()
00164 {
00165     return const_cast<Ast*>(
00166         const_cast<const DeclRegion *>(this)->asAst());
00167 }
00168 
00169 
00170 void DeclRegion::notifyAddDecl(Decl *decl) { }
00171 
00172 
00173 void DeclRegion::notifyRemoveDecl(Decl *decl) { }
00174 
00175 void DeclRegion::notifyObserversOfAddition(Decl *decl)
00176 {
00177     for (ObserverList::iterator iter = observers.begin();
00178          iter != observers.end(); ++iter)
00179         (*iter)->notifyAddDecl(decl);
00180 }
00181 
00182 void DeclRegion::notifyObserversOfRemoval(Decl *decl)
00183 {
00184     for (ObserverList::iterator iter = observers.begin();
00185          iter != observers.end(); ++iter)
00186         (*iter)->notifyRemoveDecl(decl);
00187 }