//===--- OperatorNameLookup.h - Operator and Precedence Lookup --*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2020 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // // This file defines interfaces for looking up operator and precedence group // declarations. // //===----------------------------------------------------------------------===// #ifndef SWIFT_AST_OPERATOR_NAME_LOOKUP_H #define SWIFT_AST_OPERATOR_NAME_LOOKUP_H #include "swift/AST/Identifier.h" #include "swift/AST/Module.h" #include "llvm/ADT/TinyPtrVector.h" namespace swift { /// Base class for infix operator and precedence group lookup results. template class OperatorLookupResultBase { protected: const DeclContext *ModuleDC; Identifier Name; TinyPtrVector Results; private: const Derived &asDerived() const { return *static_cast(this); } public: OperatorLookupResultBase(const DeclContext *moduleDC, Identifier name, TinyPtrVector &&results) : ModuleDC(moduleDC), Name(name), Results(std::move(results)) {} /// Retrieve the underlying results vector. TinyPtrVector get() && { return std::move(Results); } /// If the lookup produced a single result, returns it. Otherwise returns /// \c nullptr. DeclTy *getSingle() const { return Results.size() == 1 ? Results[0] : nullptr; } /// If the lookup produced a single result, returns it. Otherwise, emits an /// ambiguity or missing decl diagnostic, and returns \c nullptr. DeclTy *getSingleOrDiagnose(SourceLoc loc, bool forBuiltin = false) const { if (auto single = getSingle()) return single; if (isAmbiguous()) { asDerived().diagnoseAmbiguity(loc); } else { assert(!hasResults()); asDerived().diagnoseMissing(loc, forBuiltin); } return nullptr; } using const_iterator = typename decltype(Results)::const_iterator; const_iterator begin() const { return Results.begin(); } const_iterator end() const { return Results.end(); } /// Whether the lookup produced at least one result. bool hasResults() const { return !Results.empty(); } /// Whether the lookup produced multiple ambiguous results. bool isAmbiguous() const { return Results.size() > 1; } friend bool operator==(const OperatorLookupResultBase &lhs, const OperatorLookupResultBase &rhs) { return lhs.Results == rhs.Results; } friend bool operator!=(const OperatorLookupResultBase &lhs, const OperatorLookupResultBase &rhs) { return !(lhs == rhs); } friend void simple_display(llvm::raw_ostream &out, const OperatorLookupResultBase &result) { simple_display(out, result.Results); } }; /// The result of a precedence group lookup. class PrecedenceGroupLookupResult final : public OperatorLookupResultBase { friend class OperatorLookupResultBase; public: PrecedenceGroupLookupResult(const DeclContext *moduleDC, Identifier name, TinyPtrVector &&results) : OperatorLookupResultBase(moduleDC, name, std::move(results)) {} void diagnoseAmbiguity(SourceLoc loc) const; void diagnoseMissing(SourceLoc loc, bool forBuiltin) const; }; /// The result of an infix operator lookup. class InfixOperatorLookupResult final : public OperatorLookupResultBase { friend class OperatorLookupResultBase; public: InfixOperatorLookupResult(const DeclContext *moduleDC, Identifier name, TinyPtrVector &&results) : OperatorLookupResultBase(moduleDC, name, std::move(results)) {} void diagnoseAmbiguity(SourceLoc loc) const; void diagnoseMissing(SourceLoc loc, bool forBuiltin) const; }; } // end namespace swift #endif