00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00013 
00014 
00015 #ifndef COMMA_AST_SUBROUTINE_REF_HDR_GUARD
00016 #define COMMA_AST_SUBROUTINE_REF_HDR_GUARD
00017 
00018 #include "comma/ast/Decl.h"
00019 
00020 namespace comma {
00021 
00029 class SubroutineRef : public Ast {
00030 
00031     
00032     
00033     
00034     
00035     typedef llvm::SmallVector<SubroutineDecl*, 1> DeclVector;
00036 
00037 public:
00039     SubroutineRef(Location loc, SubroutineDecl *decl)
00040         : Ast(AST_SubroutineRef), loc(loc) {
00041         decls.push_back(decl);
00042     }
00043 
00048     SubroutineRef(Location loc, SubroutineDecl **decls, unsigned numDecls)
00049         : Ast(AST_SubroutineRef),
00050           decls(decls, decls + numDecls), loc(loc) {
00051         verify();
00052     }
00053 
00059     template <class I>
00060     SubroutineRef(Location loc, I begin, I end)
00061         : Ast(AST_SubroutineRef),
00062           decls(begin, end), loc(loc) {
00063         verify();
00064     }
00065 
00067     IdentifierInfo *getIdInfo() const {
00068         assert(!empty() && "Empty SubroutineRef!");
00069         return decls[0]->getIdInfo();
00070     }
00071 
00073     const char *getString() const { return getIdInfo()->getString(); }
00074 
00076     Location getLocation() const { return loc; }
00077 
00079     void addDeclaration(SubroutineDecl *srDecl);
00080 
00083     template <class Iter>
00084     void addDeclarations(Iter I, Iter E) {
00085         for ( ; I != E; ++I)
00086             addDeclaration(*I);
00087     }
00088 
00090     bool isOverloaded() const { return numDeclarations() > 1; }
00091 
00093     bool empty() const { return numDeclarations() == 0; }
00094 
00096     bool referencesFunctions() const {
00097         return empty() ? false : llvm::isa<FunctionDecl>(decls[0]);
00098     }
00099 
00101     bool referencesProcedures() const {
00102         return empty() ? false : llvm::isa<ProcedureDecl>(decls[0]);
00103     }
00104 
00106     unsigned numDeclarations() const { return decls.size(); }
00107 
00109 
00110     const SubroutineDecl *getDeclaration(unsigned i) const {
00111         assert(i < numDeclarations() && "Index out of range!");
00112         return decls[i];
00113     }
00114 
00115     SubroutineDecl *getDeclaration(unsigned i) {
00116         assert(i < numDeclarations() && "Index out of range!");
00117         return decls[i];
00118     }
00120 
00122 
00123 
00124     const SubroutineDecl *getDeclaration() const {
00125         return isResolved() ? decls[0] : 0;
00126     }
00127 
00128     SubroutineDecl *getDeclaration() {
00129         return isResolved() ? decls[0] : 0;
00130     }
00132 
00135     bool contains(const SubroutineDecl *srDecl) const;
00136 
00139     bool contains(const SubroutineType *srType) const;
00140 
00146     bool keepSubroutinesWithArity(unsigned arity);
00147 
00153     void resolve(SubroutineDecl *srDecl) {
00154         decls.clear();
00155         decls.push_back(srDecl);
00156     }
00157 
00159     bool isResolved() const { return numDeclarations() == 1; }
00160 
00162 
00163     typedef DeclVector::iterator iterator;
00164     iterator begin() { return decls.begin(); }
00165     iterator end() { return decls.end(); }
00166 
00167     typedef DeclVector::const_iterator const_iterator;
00168     const_iterator begin() const { return decls.begin(); }
00169     const_iterator end() const { return decls.end(); }
00171 
00172 private:
00175     template <class T>
00176     class SubroutineDeclIter {
00177 
00178         mutable SubroutineRef::iterator I;
00179 
00180         SubroutineDeclIter(SubroutineRef::iterator I)
00181             : I(I) { }
00182 
00184         SubroutineRef::iterator getIterator() const { return I; }
00185 
00186         friend class SubroutineRef;
00187 
00188     public:
00189         SubroutineDeclIter(const SubroutineDeclIter<T> &iter)
00190             : I(iter.I) { }
00191 
00192         T *operator *() {
00193             return llvm::cast<T>(*I);
00194         }
00195 
00196         const T *operator *() const {
00197             return llvm::cast<T>(*I);
00198         }
00199 
00200         bool operator ==(const SubroutineDeclIter &iter) const {
00201             return this->I == iter.I;
00202         }
00203 
00204         bool operator !=(const SubroutineDeclIter &iter) const {
00205             return !this->operator==(iter);
00206         }
00207 
00208         SubroutineDeclIter &operator ++() {
00209             ++I;
00210             return *this;
00211         }
00212 
00213         const SubroutineDeclIter &operator ++() const {
00214             ++I;
00215             return *this;
00216         }
00217 
00218         SubroutineDeclIter operator ++(int) const {
00219             SubroutineDeclIter tmp = *this;
00220             this->operator++();
00221             return tmp;
00222         }
00223     };
00224 
00225 public:
00227 
00228 
00229 
00230 
00231 
00232 
00233     typedef SubroutineDeclIter<FunctionDecl> fun_iterator;
00234     fun_iterator begin_functions() {
00235         if (this->referencesFunctions())
00236             return fun_iterator(begin());
00237         else
00238             return fun_iterator(end());
00239     }
00240     fun_iterator end_functions() {
00241         return fun_iterator(end());
00242     }
00243 
00244     typedef const SubroutineDeclIter<FunctionDecl> const_fun_iterator;
00245     const_fun_iterator begin_functions() const {
00246         SubroutineRef *ref = const_cast<SubroutineRef*>(this);
00247         if (this->referencesFunctions())
00248             return const_fun_iterator(ref->begin());
00249         else
00250             return const_fun_iterator(ref->end());
00251     }
00252     const_fun_iterator end_functions() const {
00253         SubroutineRef *ref = const_cast<SubroutineRef*>(this);
00254         return const_fun_iterator(ref->end());
00255     }
00256 
00257     typedef SubroutineDeclIter<ProcedureDecl> proc_iterator;
00258     proc_iterator begin_procedures() {
00259         if (this->referencesProcedures())
00260             return proc_iterator(begin());
00261         else
00262             return proc_iterator(end());
00263     }
00264     proc_iterator end_procedures() {
00265         return proc_iterator(end());
00266     }
00267 
00268     typedef const SubroutineDeclIter<ProcedureDecl> const_proc_iterator;
00269     const_proc_iterator begin_procedures() const {
00270         SubroutineRef *ref = const_cast<SubroutineRef*>(this);
00271         if (this->referencesProcedures())
00272             return const_proc_iterator(ref->begin());
00273         else
00274             return const_proc_iterator(ref->end());
00275     }
00276     const_proc_iterator end_procedures() const {
00277         SubroutineRef *ref = const_cast<SubroutineRef*>(this);
00278         return const_proc_iterator(ref->end());
00279     }
00281 
00288 
00289     iterator erase(iterator I) { return decls.erase(I); }
00290 
00291     template <class T>
00292     SubroutineDeclIter<T> erase(SubroutineDeclIter<T> SDI) {
00293         iterator I = SDI.getIterator();
00294         I = decls.erase(I);
00295         return SubroutineDeclIter<T>(I);
00296     }
00298 
00299     static bool classof(const SubroutineRef *node) { return true; }
00300     static bool classof(const Ast *node) {
00301         return node->getKind() == AST_SubroutineRef;
00302     }
00303 
00304 private:
00305     DeclVector decls;
00306     Location loc;
00307 
00310     void verify();
00311 
00315     void verify(SubroutineDecl *decl, IdentifierInfo *name, bool isaFunction);
00316 };
00317 
00318 } 
00319 
00320 #endif