00001 //===-- typecheck/IdentifierResolver.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 "IdentifierResolver.h" 00010 #include "comma/ast/Decl.h" 00011 #include "llvm/Support/Casting.h" 00012 #include <algorithm> 00013 00014 00015 using namespace comma; 00016 using llvm::dyn_cast; 00017 using llvm::cast; 00018 using llvm::isa; 00019 00020 00021 bool IdentifierResolver::ArityPred::operator()(const Decl* decl) const { 00022 if (const SubroutineDecl *sdecl = dyn_cast<SubroutineDecl>(decl)) 00023 return sdecl->getArity() != arity; 00024 if (arity == 0) 00025 return !isa<EnumLiteral>(decl); 00026 return false; 00027 } 00028 00029 bool IdentifierResolver::NullaryPred::operator()(const Decl* decl) const { 00030 if (const SubroutineDecl *sdecl = dyn_cast<SubroutineDecl>(decl)) 00031 return sdecl->getArity() == 0; 00032 return true; 00033 } 00034 00035 unsigned IdentifierResolver::numResolvedDecls() const { 00036 unsigned result = 0; 00037 result += hasDirectValue(); 00038 result += numDirectOverloads(); 00039 result += numIndirectValues(); 00040 result += numIndirectOverloads(); 00041 return result; 00042 } 00043 00044 bool IdentifierResolver::filterOverloadsWRTArity(unsigned arity) 00045 { 00046 return filterOverloads(ArityPred(arity)); 00047 } 00048 00049 bool IdentifierResolver::filterProcedures() 00050 { 00051 return filterOverloads(TypePred<ProcedureDecl>()); 00052 } 00053 00054 bool IdentifierResolver::filterFunctionals() 00055 { 00056 // FIXME: We should probably do this more efficiently. 00057 return filterOverloads(TypePred<FunctionDecl>()) || 00058 filterOverloads(TypePred<EnumLiteral>()); 00059 } 00060 00061 bool IdentifierResolver::filterNullaryOverloads() 00062 { 00063 return filterOverloads(NullaryPred()); 00064 } 00065 00066 bool IdentifierResolver::resolve(IdentifierInfo *idInfo) 00067 { 00068 Homonym *homonym = idInfo->getMetadata<Homonym>(); 00069 if (!homonym || homonym->empty()) 00070 return false; 00071 00072 for (Homonym::DirectIterator iter = homonym->beginDirectDecls(); 00073 iter != homonym->endDirectDecls(); ++iter) { 00074 Decl *candidate = *iter; 00075 if (SubroutineDecl *sdecl = dyn_cast<SubroutineDecl>(candidate)) { 00076 SubroutineType *stype = sdecl->getType(); 00077 bool duplicated = false; 00078 for (unsigned i = 0; i < directOverloads.size(); ++i) { 00079 if (SubroutineDecl *targetDecl = 00080 dyn_cast<SubroutineDecl>(directOverloads[i])) { 00081 SubroutineType *targetType = targetDecl->getType(); 00082 if (!(duplicated = stype->equals(targetType))) 00083 break; 00084 } 00085 } 00086 if (!duplicated) directOverloads.push_back(sdecl); 00087 } 00088 else if (EnumLiteral *elit = dyn_cast<EnumLiteral>(candidate)) 00089 directOverloads.push_back(elit); 00090 else if (ValueDecl *vdecl = dyn_cast<ValueDecl>(candidate)) { 00091 if (directOverloads.empty()) { 00092 directValue = vdecl; 00093 return true; 00094 } 00095 break; 00096 } 00097 } 00098 00099 // Scan the full set of imported declarations, and partition the 00100 // import decls into two sets: one containing all value declarations, the 00101 // other containing all nullary function declarations. 00102 for (Homonym::ImportIterator iter = homonym->beginImportDecls(); 00103 iter != homonym->endImportDecls(); ++iter) { 00104 Decl *candidate = *iter; 00105 if (SubroutineDecl *sdecl = dyn_cast<SubroutineDecl>(candidate)) 00106 indirectOverloads.push_back(sdecl); 00107 else if (EnumLiteral *elit = dyn_cast<EnumLiteral>(candidate)) 00108 indirectOverloads.push_back(elit); 00109 else if (ValueDecl *vdecl = dyn_cast<ValueDecl>(candidate)) 00110 indirectValues.push_back(vdecl); 00111 } 00112 00113 return numResolvedDecls() != 0; 00114 }